diff --git a/app/layout.tsx b/app/layout.tsx index 756fcce..2cc502f 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,9 +1,11 @@ import type { Metadata } from "next"; +import Sidebar from "../components/Sidebar"; +import styles from "../styles/Layout.module.css"; import "./globals.css"; export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "Hex: Unlocked", + description: "", }; export default function RootLayout({ @@ -13,7 +15,14 @@ export default function RootLayout({ }>) { return ( - {children} + +
+ +
+ {children} +
+
+ ); -} +} \ No newline at end of file diff --git a/app/page.tsx b/app/page.tsx index c5d1e04..1549a16 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,9 +1,132 @@ -import Sidebar from "./components/Sidebar" +'use client'; + +import { useState, useEffect, useMemo } from 'react'; +import { useInventoryStore } from '@/store/useInventoryStore'; +import styles from '../styles/Home.module.css'; export default function Home() { - return ( -
- -
- ); + const store = useInventoryStore(); + + const [charCount, setCharCount] = useState(0); + const [custCount, setCustCount] = useState(0); + const [itemsCount, setItemsCount] = useState(0); + const [offeringsCount, setOfferingsCount] = useState(0); + const [dlcsCount, setDlcsCount] = useState(0); + + const [importText, setImportText] = useState(''); + + 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(() => []) + ]).then(([chars, items, offerings, customizations, dlcs]) => { + setCharCount(chars.length); + setItemsCount(items.length); + setOfferingsCount(offerings.length); + setCustCount(customizations.length); + setDlcsCount(dlcs.length); + }); + }, []); + + /* + profile handling + */ + const handleDownload = () => { + const blob = new Blob([importText], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.download = 'profile.json'; + link.click(); + URL.revokeObjectURL(url); + }; + + const handleCopy = () => { + navigator.clipboard.writeText(importText); + }; + + const getExportText = () => { + return JSON.stringify({ + unlockedCharacters: store.unlockedCharacters, + unlockedCustomizations: store.unlockedCustomizations, + unlockedDLCs: store.unlockedDLCs, + items: store.items, + offerings: store.offerings + }, null, 2); + }; + + const handleImport = async () => { + const parsed = JSON.parse(importText); + store.importProfile(parsed); + }; + + useEffect(() => { + setImportText(getExportText()); + }, [store.unlockedCharacters, store.unlockedCustomizations, store.unlockedDLCs, store.items, store.offerings]); + + /* + 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]); + + return (
+
+

Dashboard

+

Status overview and profile management

+
+ + {/* stats cards */} +
+
+
Characters
+
{store.unlockedCharacters.length} / {charCount || '-'}
+
+
+
Customizations
+
{store.unlockedCustomizations.length} / {custCount || '-'}
+
+
+
DLCs
+
{store.unlockedDLCs.length} / {dlcsCount || '-'}
+
+
+
Items
+
{unlockedItems} / {itemsCount || '-'}
+
+
+
Offerings
+
{unlockedOfferings} / {offeringsCount || '-'}
+
+
+ + {/* profile import export stuff */} +
+
+

Profile Import / Export

+ +