ps99-api 2.3.3 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/release-on-main.yml +1 -2
- package/.idea/node-ps99-api.iml +1 -0
- package/.idea/runConfigurations/test_changing.xml +1 -1
- package/README.md +1 -1
- package/debug_currency.json +57 -0
- package/debug_goals.json +271 -0
- package/dist/ps99-api.d.ts +2 -0
- package/dist/ps99-api.js +4 -1
- package/dist/ps99-api.js.map +1 -1
- package/dist/request-client/axios.js +6 -1
- package/dist/request-client/axios.js.map +1 -1
- package/dist/responses/collection/achievement.d.ts +2 -0
- package/dist/responses/collection/guild-battle.d.ts +2 -4
- package/dist/responses/collection/index.d.ts +1 -0
- package/dist/responses/collection/index.js +15 -0
- package/dist/responses/collection/index.js.map +1 -1
- package/dist/responses/collection/rank.d.ts +1 -0
- package/dist/responses/collection/rarity.d.ts +1 -0
- package/dist/responses/collection/seed.d.ts +1 -0
- package/dist/responses/exists.d.ts +2 -0
- package/example-web/react/package-lock.json +1504 -1470
- package/example-web/react2/package-lock.json +3082 -2759
- package/example-web/react2/package.json +6 -1
- package/example-web/react2/public/assets/gold_variant_icon.png +0 -0
- package/example-web/react2/public/assets/hot_cocoa_egg.png +0 -0
- package/example-web/react2/public/index.html +34 -31
- package/example-web/react2/src/App.tsx +6 -9
- package/example-web/react2/src/assets/guild_placeholder.png +0 -0
- package/example-web/react2/src/components/AchievementsComponent.tsx +78 -30
- package/example-web/react2/src/components/BoostsComponent.tsx +18 -14
- package/example-web/react2/src/components/BoothsComponent.tsx +24 -22
- package/example-web/react2/src/components/BoxesComponent.tsx +46 -21
- package/example-web/react2/src/components/BuffsComponent.tsx +83 -13
- package/example-web/react2/src/components/CharmsComponent.tsx +47 -29
- package/example-web/react2/src/components/CollectionConfigIndex.tsx +398 -35
- package/example-web/react2/src/components/CollectionsIndex.tsx +132 -23
- package/example-web/react2/src/components/CollectionsLayout.tsx +50 -0
- package/example-web/react2/src/components/CurrencyComponent.tsx +59 -50
- package/example-web/react2/src/components/DynamicCollectionConfigData.tsx +178 -11
- package/example-web/react2/src/components/EggsComponent.tsx +77 -44
- package/example-web/react2/src/components/EnchantsComponent.tsx +84 -34
- package/example-web/react2/src/components/FishingRodsComponent.tsx +38 -31
- package/example-web/react2/src/components/Footer.tsx +75 -18
- package/example-web/react2/src/components/FruitsComponent.tsx +41 -25
- package/example-web/react2/src/components/GenericFetchComponent.tsx +40 -22
- package/example-web/react2/src/components/GuildBattlesComponent.tsx +93 -65
- package/example-web/react2/src/components/Header.tsx +5 -37
- package/example-web/react2/src/components/HomePage.tsx +16 -16
- package/example-web/react2/src/components/HoverboardsComponent.tsx +25 -37
- package/example-web/react2/src/components/ImageComponent.tsx +255 -45
- package/example-web/react2/src/components/ItemCard.tsx +240 -0
- package/example-web/react2/src/components/LootboxesComponent.tsx +24 -16
- package/example-web/react2/src/components/MasteryComponent.tsx +93 -37
- package/example-web/react2/src/components/MerchantsComponent.tsx +46 -28
- package/example-web/react2/src/components/MiscItemsComponent.tsx +28 -26
- package/example-web/react2/src/components/PetsComponent.tsx +115 -46
- package/example-web/react2/src/components/PotionsComponent.tsx +53 -36
- package/example-web/react2/src/components/RandomEventsComponent.tsx +39 -35
- package/example-web/react2/src/components/RanksComponent.tsx +187 -71
- package/example-web/react2/src/components/RarityComponent.tsx +124 -13
- package/example-web/react2/src/components/RebirthsComponent.tsx +37 -26
- package/example-web/react2/src/components/SecretRoomsComponent.tsx +7 -13
- package/example-web/react2/src/components/SeedsComponent.tsx +45 -32
- package/example-web/react2/src/components/ShovelsComponent.tsx +23 -18
- package/example-web/react2/src/components/Sidebar.tsx +105 -0
- package/example-web/react2/src/components/SprinklersComponent.tsx +27 -19
- package/example-web/react2/src/components/Tooltip.tsx +36 -0
- package/example-web/react2/src/components/UltimatesComponent.tsx +29 -24
- package/example-web/react2/src/components/UpgradesComponent.tsx +99 -55
- package/example-web/react2/src/components/WateringCansComponent.tsx +23 -21
- package/example-web/react2/src/components/WorldsComponent.tsx +27 -24
- package/example-web/react2/src/components/XPPotionsComponent.tsx +29 -19
- package/example-web/react2/src/components/ZoneFlagsComponent.tsx +27 -23
- package/example-web/react2/src/components/ZonesComponent.tsx +56 -73
- package/example-web/react2/src/constants/collectionIcons.ts +29 -0
- package/example-web/react2/src/context/CollectionDataContext.tsx +62 -0
- package/example-web/react2/src/hooks/useExpandableList.ts +38 -0
- package/example-web/react2/src/hooks/useItemResolution.ts +351 -0
- package/example-web/react2/src/index.css +257 -0
- package/example-web/react2/src/index.tsx +2 -1
- package/example-web/react2/temp_model.rbxm +0 -0
- package/example-web/react2/webpack.config.js +103 -47
- package/package.json +11 -11
- package/ranks.json +1 -0
- package/repro_collection_fetch.ts +33 -0
- package/repro_image_fetch.ts +50 -0
- package/src/__tests__/__snapshots__/ps99-api-changes.ts.snap +34841 -10439
- package/src/__tests__/__snapshots__/ps99-api-live.ts.snap +160667 -67217
- package/src/ps99-api.ts +9 -5
- package/src/request-client/axios.ts +6 -2
- package/src/responses/collection/achievement.ts +2 -0
- package/src/responses/collection/guild-battle.ts +2 -4
- package/src/responses/collection/index.ts +1 -0
- package/src/responses/collection/rank.ts +1 -0
- package/src/responses/collection/rarity.ts +1 -0
- package/src/responses/collection/seed.ts +1 -0
- package/src/responses/exists.ts +2 -0
- package/tsconfig.json +1 -1
- package/example-web/react2/public/service-worker.js +0 -63
|
@@ -17,15 +17,20 @@
|
|
|
17
17
|
"ps99-api": "file:../..",
|
|
18
18
|
"react": "^18.3.1",
|
|
19
19
|
"react-dom": "^18.3.1",
|
|
20
|
-
"react-router-dom": "^6.24.1"
|
|
20
|
+
"react-router-dom": "^6.24.1",
|
|
21
|
+
"react-virtualized-auto-sizer": "^2.0.3",
|
|
22
|
+
"react-window": "^2.2.7"
|
|
21
23
|
},
|
|
22
24
|
"devDependencies": {
|
|
23
25
|
"@types/react": "^18.3.3",
|
|
24
26
|
"@types/react-dom": "^18.3.0",
|
|
27
|
+
"@types/react-virtualized-auto-sizer": "^1.0.4",
|
|
28
|
+
"@types/react-window": "^1.8.8",
|
|
25
29
|
"clean-webpack-plugin": "^4.0.0",
|
|
26
30
|
"copy-webpack-plugin": "^12.0.2",
|
|
27
31
|
"css-loader": "^7.1.2",
|
|
28
32
|
"html-webpack-plugin": "^5.6.0",
|
|
33
|
+
"style-loader": "^4.0.0",
|
|
29
34
|
"ts-loader": "^9.5.1",
|
|
30
35
|
"typescript": "^5.5.3",
|
|
31
36
|
"webpack": "^5.92.1",
|
|
Binary file
|
|
Binary file
|
|
@@ -1,33 +1,36 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
</
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Pet Simulator 99 API</title>
|
|
8
|
+
<link rel="manifest" href="/node-ps99-api/manifest.json" />
|
|
9
|
+
<link rel="icon" href="/node-ps99-api/icons/icon-192x192.png" />
|
|
10
|
+
</head>
|
|
11
|
+
|
|
12
|
+
<body>
|
|
13
|
+
<div id="root"></div>
|
|
14
|
+
|
|
15
|
+
<script>
|
|
16
|
+
// if ("serviceWorker" in navigator) {
|
|
17
|
+
// window.addEventListener("load", function () {
|
|
18
|
+
// navigator.serviceWorker
|
|
19
|
+
// .register("/node-ps99-api/service-worker.js")
|
|
20
|
+
// .then(
|
|
21
|
+
// function (registration) {
|
|
22
|
+
// console.log(
|
|
23
|
+
// "ServiceWorker registration successful with scope: ",
|
|
24
|
+
// registration.scope,
|
|
25
|
+
// );
|
|
26
|
+
// },
|
|
27
|
+
// function (error) {
|
|
28
|
+
// console.log("ServiceWorker registration failed: ", error);
|
|
29
|
+
// },
|
|
30
|
+
// );
|
|
31
|
+
// });
|
|
32
|
+
// }
|
|
33
|
+
</script>
|
|
34
|
+
</body>
|
|
35
|
+
|
|
36
|
+
</html>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { HashRouter as Router, Routes, Route } from "react-router-dom";
|
|
2
|
+
import { HashRouter as Router, Routes, Route, Navigate } from "react-router-dom";
|
|
3
3
|
import HomePage from "./components/HomePage";
|
|
4
4
|
import Header from "./components/Header";
|
|
5
5
|
import CollectionsIndex from "./components/CollectionsIndex";
|
|
6
6
|
import CollectionConfigIndex from "./components/CollectionConfigIndex";
|
|
7
7
|
import DynamicCollectionConfigData from "./components/DynamicCollectionConfigData";
|
|
8
|
+
import CollectionsLayout from "./components/CollectionsLayout";
|
|
8
9
|
import Footer from "./components/Footer";
|
|
9
10
|
|
|
10
11
|
const App: React.FC = () => {
|
|
@@ -14,14 +15,10 @@ const App: React.FC = () => {
|
|
|
14
15
|
<Routes>
|
|
15
16
|
<Route path="/" element={<HomePage />} />
|
|
16
17
|
<Route path="/collections" element={<CollectionsIndex />} />
|
|
17
|
-
<Route
|
|
18
|
-
path="/collections/:collectionName"
|
|
19
|
-
element={<
|
|
20
|
-
|
|
21
|
-
<Route
|
|
22
|
-
path="/collections/:collectionName/:configName"
|
|
23
|
-
element={<DynamicCollectionConfigData />}
|
|
24
|
-
/>
|
|
18
|
+
<Route element={<CollectionsLayout />}>
|
|
19
|
+
<Route path="/collections/:collectionName" element={<CollectionConfigIndex />} />
|
|
20
|
+
<Route path="/collections/:collectionName/:configName" element={<DynamicCollectionConfigData />} />
|
|
21
|
+
</Route>
|
|
25
22
|
</Routes>
|
|
26
23
|
<Footer />
|
|
27
24
|
</Router>
|
|
Binary file
|
|
@@ -1,40 +1,88 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { CollectionConfigData } from "ps99-api";
|
|
3
|
-
import { GenericFetchComponent } from "./GenericFetchComponent";
|
|
4
3
|
import ImageComponent from "./ImageComponent";
|
|
4
|
+
import ItemCard from "./ItemCard";
|
|
5
|
+
import { useItemResolution } from "../hooks/useItemResolution";
|
|
6
|
+
import { useExpandableList } from "../hooks/useExpandableList";
|
|
5
7
|
|
|
6
8
|
const AchievementsComponent: React.FC<{
|
|
7
|
-
configData
|
|
9
|
+
configData: CollectionConfigData<"Achievements">;
|
|
8
10
|
}> = ({ configData }) => {
|
|
11
|
+
const { resolveItem, getRarityColor, loading } = useItemResolution();
|
|
12
|
+
const { expandedIndices, toggle, expandAll, collapseAll, isExpanded } = useExpandableList(configData.Tiers.length);
|
|
13
|
+
|
|
14
|
+
if (loading) return <div>Loading data...</div>;
|
|
15
|
+
|
|
9
16
|
return (
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
17
|
+
<div style={{ width: "100%", height: "100%", boxSizing: "border-box" }}>
|
|
18
|
+
|
|
19
|
+
<div style={{ marginBottom: '20px', display: 'flex', gap: '10px', justifyContent: 'center' }}>
|
|
20
|
+
<button onClick={expandAll} style={{ padding: '8px 16px', borderRadius: '8px', border: '1px solid #ddd', background: '#fff', cursor: 'pointer' }}>Expand All</button>
|
|
21
|
+
<button onClick={collapseAll} style={{ padding: '8px 16px', borderRadius: '8px', border: '1px solid #ddd', background: '#fff', cursor: 'pointer' }}>Collapse All</button>
|
|
22
|
+
</div>
|
|
23
|
+
<div style={{ maxWidth: "150px", margin: "0 auto 20px" }}>
|
|
24
|
+
<ImageComponent src={configData.Icon} alt={configData.Name} />
|
|
25
|
+
</div>
|
|
26
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "20px" }}>
|
|
27
|
+
{configData.Tiers.map((tier, index) => (
|
|
28
|
+
<div
|
|
29
|
+
key={index}
|
|
30
|
+
style={{
|
|
31
|
+
border: "1px solid #eee",
|
|
32
|
+
padding: "15px",
|
|
33
|
+
borderRadius: "12px",
|
|
34
|
+
textAlign: 'left'
|
|
35
|
+
}}
|
|
36
|
+
>
|
|
37
|
+
<div
|
|
38
|
+
onClick={() => toggle(index)}
|
|
39
|
+
style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', cursor: 'pointer', paddingBottom: isExpanded(index) ? '10px' : '0' }}
|
|
40
|
+
>
|
|
41
|
+
<h3 style={{ margin: 0, fontSize: '1.2em', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
42
|
+
{isExpanded(index) ? '▼' : '▶'} {tier.Title}
|
|
43
|
+
</h3>
|
|
44
|
+
<div style={{ display: "flex", gap: "10px" }}>
|
|
45
|
+
<span className="badge">Difficulty: {tier.Difficulty.Name}</span>
|
|
46
|
+
<span className="badge">Amount: {tier.Amount.toLocaleString()} {(tier.Desc.match(/{amount}\s*([a-zA-Z]+)/)?.[1] || '')}</span>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
{isExpanded(index) && (
|
|
51
|
+
<div style={{ borderTop: '1px solid #eee', paddingTop: '15px' }}>
|
|
52
|
+
|
|
53
|
+
<p style={{ marginBottom: '15px', color: '#555' }}>{tier.Desc.replace("{amount}", tier.Amount.toLocaleString())}</p>
|
|
54
|
+
|
|
55
|
+
<h4 style={{ fontSize: '1em', marginBottom: '10px' }}>Rewards</h4>
|
|
56
|
+
<div
|
|
57
|
+
style={{
|
|
58
|
+
display: "grid",
|
|
59
|
+
gridTemplateColumns: "repeat(auto-fill, minmax(140px, 1fr))",
|
|
60
|
+
gap: "10px",
|
|
61
|
+
}}
|
|
62
|
+
>
|
|
63
|
+
{tier.Rewards.map((reward, rewardIndex) => {
|
|
64
|
+
const id = reward.Reward._data.id;
|
|
65
|
+
const amount = reward.Reward._data._am;
|
|
66
|
+
const itemData = resolveItem(id);
|
|
67
|
+
return (
|
|
68
|
+
<div key={rewardIndex}>
|
|
69
|
+
<ItemCard
|
|
70
|
+
id={id}
|
|
71
|
+
amount={amount}
|
|
72
|
+
label={id}
|
|
73
|
+
itemData={itemData}
|
|
74
|
+
rarityColor={itemData?.rarity ? getRarityColor(itemData.rarity) : null}
|
|
75
|
+
/>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
})}
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
)}
|
|
82
|
+
</div>
|
|
83
|
+
))}
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
38
86
|
);
|
|
39
87
|
};
|
|
40
88
|
|
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { CollectionConfigData } from "ps99-api";
|
|
3
|
-
import
|
|
4
|
-
import ImageComponent from "./ImageComponent";
|
|
3
|
+
import ItemCard from "./ItemCard";
|
|
5
4
|
|
|
6
5
|
const BoostsComponent: React.FC<{
|
|
7
|
-
configData
|
|
6
|
+
configData: CollectionConfigData<"Boosts">;
|
|
8
7
|
}> = ({ configData }) => {
|
|
9
8
|
return (
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
9
|
+
<div style={{ width: '100%', height: '100%', boxSizing: 'border-box' }}>
|
|
10
|
+
<ItemCard
|
|
11
|
+
id={configData.DisplayName}
|
|
12
|
+
amount={1}
|
|
13
|
+
label={configData.DisplayName}
|
|
14
|
+
itemData={{
|
|
15
|
+
icon: configData.Icon,
|
|
16
|
+
rarity: undefined,
|
|
17
|
+
name: configData.DisplayName
|
|
18
|
+
}}
|
|
19
|
+
rarityColor={null}
|
|
20
|
+
/>
|
|
21
|
+
<div style={{ marginTop: '10px', fontSize: '0.9em', color: '#666', textAlign: 'center' }}>
|
|
22
|
+
<p>Max Percent: {configData.MaximumPercent}%</p>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
21
25
|
);
|
|
22
26
|
};
|
|
23
27
|
|
|
@@ -1,31 +1,33 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { CollectionConfigData } from "ps99-api";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import ItemCard from "./ItemCard";
|
|
4
|
+
import { useItemResolution } from "../hooks/useItemResolution";
|
|
5
5
|
|
|
6
6
|
const BoothsComponent: React.FC<{
|
|
7
|
-
configData
|
|
7
|
+
configData: CollectionConfigData<"Booths">;
|
|
8
8
|
}> = ({ configData }) => {
|
|
9
|
+
const { getRarityColor } = useItemResolution();
|
|
10
|
+
const rarityColor = configData.Rarity ? getRarityColor(configData.Rarity) : null;
|
|
11
|
+
|
|
9
12
|
return (
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
/>
|
|
13
|
+
<div style={{ width: '100%', height: '100%', boxSizing: 'border-box' }}>
|
|
14
|
+
<ItemCard
|
|
15
|
+
id={configData.DisplayName}
|
|
16
|
+
amount={1}
|
|
17
|
+
label={configData.DisplayName}
|
|
18
|
+
itemData={{
|
|
19
|
+
icon: configData.Icon,
|
|
20
|
+
rarity: configData.Rarity,
|
|
21
|
+
name: configData.DisplayName
|
|
22
|
+
}}
|
|
23
|
+
rarityColor={rarityColor}
|
|
24
|
+
/>
|
|
25
|
+
<div style={{ marginTop: '10px', fontSize: '0.9em', color: '#666', textAlign: 'center' }}>
|
|
26
|
+
<p>{configData.Desc}</p>
|
|
27
|
+
{configData.ProductId && <p>ID: {configData.ProductId}</p>}
|
|
28
|
+
{configData.DiamondPrice && <p>💎 {configData.DiamondPrice}</p>}
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
29
31
|
);
|
|
30
32
|
};
|
|
31
33
|
|
|
@@ -1,34 +1,59 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { CollectionConfigData } from "ps99-api";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import ItemCard from "./ItemCard";
|
|
4
|
+
import { useItemResolution } from "../hooks/useItemResolution";
|
|
5
5
|
|
|
6
6
|
const BoxesComponent: React.FC<{
|
|
7
|
-
configData
|
|
7
|
+
configData: CollectionConfigData<"Boxes">;
|
|
8
8
|
}> = ({ configData }) => {
|
|
9
|
+
const { getRarityColor } = useItemResolution();
|
|
10
|
+
const rarityColor = configData.Rarity ? getRarityColor(configData.Rarity) : null;
|
|
11
|
+
|
|
9
12
|
return (
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
<div style={{ width: '100%', height: '100%', boxSizing: 'border-box' }}>
|
|
14
|
+
|
|
15
|
+
<div style={{ maxWidth: '300px', margin: '0 auto 15px auto' }}>
|
|
16
|
+
<ItemCard
|
|
17
|
+
id={configData.DisplayName}
|
|
18
|
+
amount={1}
|
|
19
|
+
label={configData.DisplayName}
|
|
20
|
+
itemData={{
|
|
21
|
+
icon: configData.Icons && configData.Icons.length > 0 ? configData.Icons[0].Icon : undefined,
|
|
22
|
+
rarity: configData.Rarity,
|
|
23
|
+
name: configData.DisplayName
|
|
24
|
+
}}
|
|
25
|
+
rarityColor={rarityColor}
|
|
26
|
+
/>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div style={{ marginBottom: '20px', fontSize: '0.9em', color: '#666', textAlign: 'center' }}>
|
|
30
|
+
<p>{configData.Desc}</p>
|
|
31
|
+
<p style={{ fontWeight: 'bold' }}>Capacity: {configData.Capacity}</p>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
{configData.Icons && configData.Icons.length > 0 && (
|
|
14
35
|
<div>
|
|
15
|
-
<
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
36
|
+
<h3 style={{ fontSize: '1.2em', borderBottom: '1px solid #eee', paddingBottom: '5px' }}>Variants</h3>
|
|
37
|
+
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(120px, 1fr))", gap: "10px", marginTop: '15px' }}>
|
|
38
|
+
{configData.Icons.map((icon, index) => (
|
|
39
|
+
<div key={index} style={{ textAlign: 'center' }}>
|
|
40
|
+
<ItemCard
|
|
41
|
+
id={icon.Name}
|
|
42
|
+
amount={1}
|
|
43
|
+
label={icon.Name}
|
|
44
|
+
itemData={{
|
|
45
|
+
icon: icon.Icon,
|
|
46
|
+
rarity: configData.Rarity,
|
|
47
|
+
name: icon.Name
|
|
48
|
+
}}
|
|
49
|
+
rarityColor={rarityColor}
|
|
50
|
+
/>
|
|
51
|
+
</div>
|
|
27
52
|
))}
|
|
28
|
-
</
|
|
53
|
+
</div>
|
|
29
54
|
</div>
|
|
30
55
|
)}
|
|
31
|
-
|
|
56
|
+
</div>
|
|
32
57
|
);
|
|
33
58
|
};
|
|
34
59
|
|
|
@@ -1,24 +1,94 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { CollectionConfigData } from "ps99-api";
|
|
3
3
|
import { GenericFetchComponent } from "./GenericFetchComponent";
|
|
4
|
+
import ItemCard from "./ItemCard";
|
|
4
5
|
|
|
5
6
|
const BuffsComponent: React.FC<{
|
|
6
|
-
configData
|
|
7
|
+
configData: CollectionConfigData<"Buffs">;
|
|
7
8
|
}> = ({ configData }) => {
|
|
8
9
|
return (
|
|
9
|
-
<
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
<div style={{ width: '100%', height: '100%', boxSizing: 'border-box' }}>
|
|
11
|
+
|
|
12
|
+
{/* Grid Layout */}
|
|
13
|
+
<div style={{
|
|
14
|
+
display: 'grid',
|
|
15
|
+
gridTemplateColumns: '1fr 1fr',
|
|
16
|
+
gap: '40px',
|
|
17
|
+
alignItems: 'start'
|
|
18
|
+
}}>
|
|
19
|
+
|
|
20
|
+
{/* Left Column: Associated Item (Visuals) */}
|
|
21
|
+
<div style={{
|
|
22
|
+
background: '#f9f9f9',
|
|
23
|
+
padding: '30px',
|
|
24
|
+
borderRadius: '24px',
|
|
25
|
+
border: '2px solid #eee',
|
|
26
|
+
display: 'flex',
|
|
27
|
+
flexDirection: 'column',
|
|
28
|
+
alignItems: 'center',
|
|
29
|
+
gap: '20px'
|
|
30
|
+
}}>
|
|
31
|
+
{configData.AssociatedItemClass === "Misc" && (
|
|
32
|
+
<>
|
|
33
|
+
<h3 style={{ margin: 0, color: '#888', textTransform: 'uppercase', fontSize: '0.9rem' }}>Associated Item</h3>
|
|
34
|
+
<div style={{ width: '100%', maxWidth: '300px' }}>
|
|
35
|
+
<GenericFetchComponent
|
|
36
|
+
collectionName="MiscItems"
|
|
37
|
+
configName={configData.AssociatedItemID}
|
|
38
|
+
render={(data: any) => (
|
|
39
|
+
<ItemCard
|
|
40
|
+
id={data.DisplayName}
|
|
41
|
+
amount={1}
|
|
42
|
+
label={data.DisplayName}
|
|
43
|
+
itemData={{
|
|
44
|
+
icon: data.Icon,
|
|
45
|
+
rarity: data.Rarity,
|
|
46
|
+
name: data.DisplayName
|
|
47
|
+
}}
|
|
48
|
+
// Simple non-interactive card style
|
|
49
|
+
/>
|
|
50
|
+
)}
|
|
51
|
+
/>
|
|
52
|
+
</div>
|
|
53
|
+
</>
|
|
54
|
+
)}
|
|
55
|
+
{/* If no associated item, maybe show a generic buff icon? */}
|
|
19
56
|
</div>
|
|
20
|
-
|
|
21
|
-
|
|
57
|
+
|
|
58
|
+
{/* Right Column: Stats & Data */}
|
|
59
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}>
|
|
60
|
+
|
|
61
|
+
{/* Stats Grid */}
|
|
62
|
+
<div style={{
|
|
63
|
+
display: 'grid',
|
|
64
|
+
gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
|
|
65
|
+
gap: '20px',
|
|
66
|
+
width: '100%'
|
|
67
|
+
}}>
|
|
68
|
+
<div style={{ background: '#e0f7fa', padding: '15px', borderRadius: '12px', border: '1px solid #b2ebf2' }}>
|
|
69
|
+
<strong style={{ display: 'block', fontSize: '0.9rem', color: '#006064', marginBottom: '5px' }}>CLASS</strong>
|
|
70
|
+
<span style={{ fontSize: '1.2rem', fontWeight: 'bold', color: '#00838f' }}>{configData.AssociatedItemClass}</span>
|
|
71
|
+
</div>
|
|
72
|
+
<div style={{ background: '#fff3e0', padding: '15px', borderRadius: '12px', border: '1px solid #ffe0b2' }}>
|
|
73
|
+
<strong style={{ display: 'block', fontSize: '0.9rem', color: '#e65100', marginBottom: '5px' }}>DURATION</strong>
|
|
74
|
+
<span style={{ fontSize: '1.2rem', fontWeight: 'bold', color: '#ef6c00' }}>{configData.Length}s</span>
|
|
75
|
+
</div>
|
|
76
|
+
{configData.IgnoreInstancePause && (
|
|
77
|
+
<div style={{ background: '#fce4ec', padding: '15px', borderRadius: '12px', border: '1px solid #f8bbd0' }}>
|
|
78
|
+
<strong style={{ display: 'block', fontSize: '0.9rem', color: '#880e4f', marginBottom: '5px' }}>SPECIAL</strong>
|
|
79
|
+
<span style={{ fontSize: '1.2rem', fontWeight: 'bold', color: '#ad1457' }}>Ignores Pause</span>
|
|
80
|
+
</div>
|
|
81
|
+
)}
|
|
82
|
+
<div style={{ background: '#f5f5f5', padding: '15px', borderRadius: '12px', border: '1px solid #ddd' }}>
|
|
83
|
+
<strong style={{ display: 'block', fontSize: '0.9rem', color: '#666', marginBottom: '5px' }}>ITEM ID</strong>
|
|
84
|
+
<span style={{ fontSize: '0.9rem', fontFamily: 'monospace', color: '#333' }}>{configData.AssociatedItemID}</span>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
22
92
|
);
|
|
23
93
|
};
|
|
24
94
|
|
|
@@ -1,40 +1,58 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { CollectionConfigData } from "ps99-api";
|
|
3
|
-
import
|
|
3
|
+
import ItemCard from "./ItemCard";
|
|
4
4
|
import ImageComponent from "./ImageComponent";
|
|
5
|
+
import { useItemResolution } from "../hooks/useItemResolution";
|
|
5
6
|
|
|
6
7
|
const CharmsComponent: React.FC<{
|
|
7
|
-
configData
|
|
8
|
+
configData: CollectionConfigData<"Charms">;
|
|
8
9
|
}> = ({ configData }) => {
|
|
10
|
+
const { getRarityColor } = useItemResolution();
|
|
11
|
+
|
|
9
12
|
return (
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
<p>Base Tier
|
|
18
|
-
<p>Max Tier
|
|
19
|
-
{
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
<
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
13
|
+
<div style={{ width: '100%', height: '100%', boxSizing: 'border-box' }}>
|
|
14
|
+
|
|
15
|
+
<div style={{ display: 'flex', gap: '20px', justifyContent: 'center', flexWrap: 'wrap', marginBottom: '20px' }}>
|
|
16
|
+
<div style={{ width: '150px' }}>
|
|
17
|
+
<ImageComponent src={configData.Icon} alt={configData.Tiers[0].DisplayName} />
|
|
18
|
+
</div>
|
|
19
|
+
<div style={{ textAlign: 'left', minWidth: '200px' }}>
|
|
20
|
+
<p><strong>Base Tier:</strong> {configData.BaseTier}</p>
|
|
21
|
+
<p><strong>Max Tier:</strong> {configData.MaxTier}</p>
|
|
22
|
+
{configData.DiminishPowerThreshold && <p><strong>Diminish:</strong> {configData.DiminishPowerThreshold}</p>}
|
|
23
|
+
{configData.Unique && <span className="badge">Unique</span>}
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<div style={{ marginTop: '20px' }}>
|
|
28
|
+
<h3 style={{ fontSize: '1.2em', borderBottom: '1px solid #eee', paddingBottom: '5px' }}>Tiers</h3>
|
|
29
|
+
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(220px, 1fr))", gap: "15px", marginTop: '15px' }}>
|
|
30
|
+
{configData.Tiers.map((tier, index) => {
|
|
31
|
+
const rarityColor = tier.Rarity ? getRarityColor(tier.Rarity) : null;
|
|
32
|
+
return (
|
|
33
|
+
<div key={index}>
|
|
34
|
+
<ItemCard
|
|
35
|
+
id={tier.DisplayName}
|
|
36
|
+
amount={1}
|
|
37
|
+
label={tier.DisplayName}
|
|
38
|
+
tn={index + 1}
|
|
39
|
+
itemData={{
|
|
40
|
+
icon: configData.Icon,
|
|
41
|
+
rarity: tier.Rarity,
|
|
42
|
+
name: tier.DisplayName
|
|
43
|
+
}}
|
|
44
|
+
rarityColor={rarityColor}
|
|
45
|
+
/>
|
|
46
|
+
<div style={{ marginTop: '10px', fontSize: '0.9em', color: '#666', textAlign: 'center' }}>
|
|
47
|
+
<p>{tier.Desc}</p>
|
|
48
|
+
<p style={{ fontWeight: 'bold' }}>Power: {tier.Power}</p>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
})}
|
|
35
53
|
</div>
|
|
36
|
-
|
|
37
|
-
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
38
56
|
);
|
|
39
57
|
};
|
|
40
58
|
|