diff --git a/app/page.tsx b/app/page.tsx
index cd4b7e1..d0487f7 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -4,7 +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';
+import { fetchCharacters, fetchItems, fetchOfferings, fetchCustomizations, fetchDLCs, fetchAddons, fetchPerks } from '@/lib/db';
export default function Home() {
const store = useInventoryStore();
@@ -14,6 +14,8 @@ export default function Home() {
const [itemsCount, setItemsCount] = useState(0);
const [offeringsCount, setOfferingsCount] = useState(0);
const [dlcsCount, setDlcsCount] = useState(0);
+ const [addonsCount, setAddonsCount] = useState(0);
+ const [perksCount, setPerksCount] = useState(0);
const [importText, setImportText] = useState('');
@@ -23,13 +25,17 @@ export default function Home() {
fetchItems(),
fetchOfferings(),
fetchCustomizations(),
- fetchDLCs()
- ]).then(([chars, items, offerings, customizations, dlcs]) => {
+ fetchDLCs(),
+ fetchAddons(),
+ fetchPerks()
+ ]).then(([chars, items, offerings, customizations, dlcs, addons, perks]) => {
setCharCount(chars.length);
setItemsCount(items.length);
setOfferingsCount(offerings.length);
setCustCount(customizations.length);
setDlcsCount(dlcs.filter(isNamedDLC).length);
+ setAddonsCount(addons.length);
+ setPerksCount(perks.length);
});
}, []);
@@ -55,25 +61,33 @@ export default function Home() {
unlockedCharacters: store.unlockedCharacters,
unlockedCustomizations: store.unlockedCustomizations,
unlockedDLCs: store.unlockedDLCs,
+ unlockedPerks: store.unlockedPerks,
items: store.items,
- offerings: store.offerings
+ offerings: store.offerings,
+ addons: store.addons
}, null, 2);
};
const handleImport = async () => {
- const parsed = JSON.parse(importText);
- store.importProfile(parsed);
+ try {
+ const parsed = JSON.parse(importText);
+ store.importProfile(parsed);
+ } catch (e) {
+ console.error("Invalid JSON", e);
+ }
};
useEffect(() => {
setImportText(getExportText());
- }, [store.unlockedCharacters, store.unlockedCustomizations, store.unlockedDLCs, store.items, store.offerings]);
+ }, [store.unlockedCharacters, store.unlockedCustomizations, store.unlockedDLCs, store.unlockedPerks, store.items, store.offerings, store.addons]);
/*
stats
*/
const unlockedItems = useMemo(() => Object.values(store.items).filter(qty => qty > 0).length, [store.items]);
const unlockedOfferings = useMemo(() => Object.values(store.offerings).filter(qty => qty > 0).length, [store.offerings]);
+ const unlockedAddons = useMemo(() => Object.values(store.addons).filter(qty => qty > 0).length, [store.addons]);
+ const unlockedPerks = store.unlockedPerks.length;
return (
@@ -85,27 +99,35 @@ export default function Home() {
Characters
-
{store.unlockedCharacters.length} / {charCount || '-'}
+
{store.unlockedCharacters.length} / {charCount || '-'}
Customizations
-
{store.unlockedCustomizations.length} / {custCount || '-'}
+
{store.unlockedCustomizations.length} / {custCount || '-'}
DLCs
-
{store.unlockedDLCs.length} / {dlcsCount || '-'}
+
{store.unlockedDLCs.length} / {dlcsCount || '-'}
Items
-
{unlockedItems} / {itemsCount || '-'}
+
{unlockedItems} / {itemsCount || '-'}
Offerings
-
{unlockedOfferings} / {offeringsCount || '-'}
+
{unlockedOfferings} / {offeringsCount || '-'}
+
+
+
Addons
+
{unlockedAddons} / {addonsCount || '-'}
+
+
+
Perks
+
{unlockedPerks} / {perksCount || '-'}
- {/* profile import export stuff */}
+ {/* Control panels */}
Profile Import / Export
diff --git a/styles/Home.module.css b/styles/Home.module.css
index 332edb1..e07d782 100644
--- a/styles/Home.module.css
+++ b/styles/Home.module.css
@@ -29,11 +29,23 @@
.statsGrid {
display: grid;
- grid-template-columns: repeat(5, 1fr);
+ grid-template-columns: repeat(4, 1fr);
gap: 1.5rem;
margin-bottom: 3rem;
}
+@media (max-width: 1000px) {
+ .statsGrid {
+ grid-template-columns: repeat(3, 1fr);
+ }
+}
+
+@media (max-width: 600px) {
+ .statsGrid {
+ grid-template-columns: repeat(2, 1fr);
+ }
+}
+
.statCard {
background: #0d0d0d;
border: 1px solid #1a1a1a;
@@ -64,17 +76,30 @@
line-height: 1;
}
+.statTotal {
+ font-size: 0.9rem;
+ color: #555555;
+}
+
.panelGrid {
display: grid;
- grid-template-columns: 1fr;
+ grid-template-columns: 1fr 1.2fr;
gap: 2rem;
}
+@media (max-width: 900px) {
+ .panelGrid {
+ grid-template-columns: 1fr;
+ }
+}
+
.card {
background: #0d0d0d;
border: 1px solid #1a1a1a;
border-top: 3px solid #630000;
padding: 2rem;
+ display: flex;
+ flex-direction: column;
}
.cardTitle {
@@ -83,12 +108,7 @@
color: #ffffff;
margin: 0 0 1.5rem 0;
letter-spacing: 0.05em;
-}
-
-.formatBtnActive {
- background: #a30000;
- border-color: #ff0000;
- color: #ffffff;
+ font-family: 'Oswald', sans-serif;
}
.textarea {
@@ -149,26 +169,84 @@
color: #ffffff;
}
-.toast {
- position: fixed;
- bottom: 2rem;
- right: 2rem;
- background: #0d0d0d;
- border: 1px solid #00ff66;
- color: #00ff66;
- padding: 1rem 1.5rem;
- font-size: 0.8rem;
- text-transform: uppercase;
+.toggleRow {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 1rem 0;
+ border-bottom: 1px solid #1a1a1a;
+}
+
+.toggleRow:last-child {
+ border-bottom: none;
+}
+
+.toggleInfo {
+ display: flex;
+ flex-direction: column;
+ gap: 0.2rem;
+ padding-right: 1.5rem;
+}
+
+.toggleLabel {
+ font-size: 0.85rem;
font-weight: bold;
- animation: slideIn 0.3s ease-out forwards;
+ text-transform: uppercase;
+ color: #ffffff;
+ letter-spacing: 0.05em;
+ font-family: 'Oswald', sans-serif;
}
-.toastError {
- border-color: #ff0000;
- color: #ff0000;
+.toggleDesc {
+ font-size: 0.68rem;
+ color: #555555;
+ line-height: 1.3;
}
-@keyframes slideIn {
- from { transform: translateY(20px); opacity: 0; }
- to { transform: translateY(0); opacity: 1; }
+.switch {
+ position: relative;
+ display: inline-block;
+ width: 48px;
+ height: 24px;
+ flex-shrink: 0;
+}
+
+.switch input {
+ opacity: 0;
+ width: 0;
+ height: 0;
+}
+
+.slider {
+ position: absolute;
+ cursor: pointer;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: #121212;
+ border: 1px solid #333333;
+ transition: 0.2s;
+}
+
+.slider:before {
+ position: absolute;
+ content: "";
+ height: 16px;
+ width: 16px;
+ left: 3px;
+ bottom: 3px;
+ background-color: #555555;
+ transition: 0.2s;
+}
+
+input:checked + .slider {
+ background-color: #2b0000;
+ border-color: #a30000;
+}
+
+input:checked + .slider:before {
+ transform: translateX(24px);
+ background-color: #a30000;
+ box-shadow: 0 0 8px rgba(163, 0, 0, 0.7);
}
\ No newline at end of file