diff --git a/src/components/Elements/MainModal/Main.jsx b/src/components/Elements/MainModal/Main.jsx index 5c87c658..0386d5c0 100644 --- a/src/components/Elements/MainModal/Main.jsx +++ b/src/components/Elements/MainModal/Main.jsx @@ -4,6 +4,7 @@ import { motion, AnimatePresence } from 'framer-motion'; import './scss/index.scss'; import Navbar from './backend/TabNavbar'; import { TabProvider, useTab } from './backend/TabContext'; +import { MarketplaceDataProvider } from 'features/marketplace/api/MarketplaceDataContext'; const Settings = lazy(() => import('../../../features/misc/views/Settings')); const Addons = lazy(() => import('../../../features/misc/views/Addons')); @@ -79,7 +80,9 @@ const MainModalContent = ({ modalClose }) => { const MainModal = ({ modalClose }) => ( - + + + ); diff --git a/src/components/Elements/MainModal/backend/Tab.jsx b/src/components/Elements/MainModal/backend/Tab.jsx index aff4e114..3171b6fd 100644 --- a/src/components/Elements/MainModal/backend/Tab.jsx +++ b/src/components/Elements/MainModal/backend/Tab.jsx @@ -21,7 +21,7 @@ import { MdOutlineAssessment as Stats, MdOutlineNewReleases as Changelog, MdInfoOutline as About, - MdOutlineExtension as Added, + MdSpaceDashboard as Added, MdAddCircleOutline as Create, MdViewAgenda as Overview, MdCollectionsBookmark as Collections, diff --git a/src/components/Elements/MainModal/backend/TabNavbar.jsx b/src/components/Elements/MainModal/backend/TabNavbar.jsx index e1ebbb0a..300e3916 100644 --- a/src/components/Elements/MainModal/backend/TabNavbar.jsx +++ b/src/components/Elements/MainModal/backend/TabNavbar.jsx @@ -2,11 +2,12 @@ import React from 'react'; import { MdSettings, MdOutlineShoppingBasket, - MdOutlineExtension, + MdSpaceDashboard, MdOutlineKeyboardArrowRight, MdClose, MdSearch, } from 'react-icons/md'; +import { IoMdPricetag } from "react-icons/io"; import { motion, AnimatePresence } from 'framer-motion'; import { useTab } from './TabContext'; import { Tooltip } from 'components/Elements'; @@ -18,8 +19,8 @@ const TabNavbar = ({ modalClose }) => { const tabs = [ { id: 'settings', label: 'Settings', icon: }, - { id: 'addons', label: 'Addons', icon: }, - { id: 'marketplace', label: 'Marketplace', icon: }, + { id: 'addons', label: 'Addons', icon: }, + { id: 'marketplace', label: 'Marketplace', icon: }, ]; const navbarLogo = ( diff --git a/src/features/marketplace/api/MarketplaceDataContext.jsx b/src/features/marketplace/api/MarketplaceDataContext.jsx new file mode 100644 index 00000000..af1751d4 --- /dev/null +++ b/src/features/marketplace/api/MarketplaceDataContext.jsx @@ -0,0 +1,53 @@ +import React, { createContext, useContext, useState, useEffect } from 'react'; +import variables from 'config/variables'; +import { sortItems } from '../../marketplace/api'; + +const MarketDataContext = createContext(); + +export const useMarketData = () => useContext(MarketDataContext); + +export const MarketplaceDataProvider = ({ children }) => { + const [done, setDone] = useState(false); + const [items, setItems] = useState([]); + const [selectedItem, setSelectedItem] = useState(null); + const controller = new AbortController(); + + const getItems = async (type = 'all') => { + setDone(false); + const dataURL = + variables.constants.API_URL + + (type === 'collections' ? '/marketplace/collections' : '/marketplace/items/' + type); + + const { data } = await ( + await fetch(dataURL, { + signal: controller.signal, + }) + ).json(); + + if (controller.signal.aborted === true) { + return; + } + + setItems(sortItems(data, 'z-a')); + setDone(true); + }; + + const getItemData = async (itemType, itemName) => { + const response = await fetch( + `${variables.constants.API_URL}/marketplace/item/${itemType}/${itemName}`, + { + signal: controller.signal, + }, + ); + const item = await response.json(); + setSelectedItem(item.data); + return new Promise((resolve) => { + resolve(item.data); + }); + }; + return ( + + {children} + + ); +}; diff --git a/src/features/marketplace/components/Items/NewItems.jsx b/src/features/marketplace/components/Items/NewItems.jsx index a77c851d..0fd9c8b0 100644 --- a/src/features/marketplace/components/Items/NewItems.jsx +++ b/src/features/marketplace/components/Items/NewItems.jsx @@ -3,15 +3,30 @@ import { motion } from 'framer-motion'; import { useState } from 'react'; import placeholderIcon from 'assets/icons/marketplace-placeholder.png'; import { useTab } from 'components/Elements/MainModal/backend/TabContext'; +import { useMarketData } from 'features/marketplace/api/MarketplaceDataContext'; function ItemCard({ item, onClick, type, onCollection, isCurator }) { + const { getItemData, selectedItem, setSelectedItem } = useMarketData(); + const { setSubTab } = useTab(); + item._onCollection = onCollection; + + const SelectItem = () => { + console.log("Item selected: ", item.display_name); + console.log("Item type: ", item.type); + getItemData(item.type, item.name).then((data) => { + console.log("Selected item: ", data); + //setSelectedItem(data); + setSubTab(data.display_name); + }); + } + return ( { const { subTab } = useTab(); @@ -27,51 +29,16 @@ const NewItemPage = () => { const [count, setCount] = useState(5); const [item, setItemData] = useState(null); const [shareModal, setShareModal] = useState(false); + const { selectedItem } = useMarketData(); - async function getItemData() { - let testType = 'quote_packs'; - // Fetch data from API - const response = await fetch( - `${variables.constants.API_URL}/marketplace/item/${testType}/${subTab}`, - { - signal: controller.signal, - }, - ); - const item = await response.json(); - console.log(item); - - const { data } = item; - - return { - data, + const getName = (name) => { + const nameMappings = { + photos: 'photo_packs', + quotes: 'quote_packs', + settings: 'preset_settings', }; - } - - useEffect(() => { - async function fetchData() { - const data = await getItemData(); - setItemData(data.data); - } - - fetchData(); - }, []); - - if (!item) { - return null; // or a loading spinner - } - - const { - onCollection, - type, - display_name, - author, - description, - version, - icon, - data, - local, - slug, - } = item; + return nameMappings[name] || name; + }; const moreInfoItem = (icon, header, text) => (
@@ -118,45 +85,45 @@ const NewItemPage = () => { {variables.getMessage('marketplace:product.details')}
- {item?.updated_at && + {selectedItem?.updated_at && moreInfoItem( , variables.getMessage('marketplace:product.updated_at'), formattedDate, )} - {item?.quotes && + {selectedItem?.quotes && moreInfoItem( , variables.getMessage('marketplace:product.no_quotes'), - item.quotes.length, + selectedItem.quotes.length, )} - {item?.photos && + {selectedItem?.photos && moreInfoItem( , variables.getMessage('marketplace:product.no_images'), - item.photos.length, + selectedItem.photos.length, )} - {item?.quotes && item?.language + {selectedItem?.quotes && selectedItem?.language ? moreInfoItem( , variables.getMessage('settings:sections.language.title'), - languageNames.of(item.language), + languageNames.of(selectedItem.language), ) : null} - {/*{moreInfoItem( + {moreInfoItem( , variables.getMessage('settings:sections.background.type.title'), variables.getMessage( - 'marketplace:' + this.getName(this.props.data.data.type), + 'marketplace:' + getName(selectedItem.type), ) || 'marketplace', - )}*/} + )}
); }; const ItemShowcase = () => { - switch (item.type) { + switch (selectedItem.type) { case 'quotes': return ( <> @@ -166,7 +133,7 @@ const NewItemPage = () => { {variables.getMessage('settings:sections.quote.title')} {variables.getMessage('settings:sections.quote.author')} - {item.quotes.slice(0, count).map((quote, index) => ( + {selectedItem.quotes.slice(0, count).map((quote, index) => ( {quote.quote} {quote.author} @@ -175,8 +142,8 @@ const NewItemPage = () => {
- count === item.quotes.length}> - {count !== item.quotes.length + count === selectedItem.quotes.length}> + {count !== selectedItem.quotes.length ? variables.getMessage('marketplace:product.show_all') : variables.getMessage('marketplace:product.show_less')} @@ -192,8 +159,8 @@ const NewItemPage = () => { {variables.getMessage('marketplace:product.setting')} {variables.getMessage('marketplace:product.value')} - {Object.entries(this.props.data.data.settings) - .slice(0, this.state.count) + {Object.entries(selectedItem.settings) + .slice(0, count) .map(([key, value]) => ( {key} @@ -204,7 +171,7 @@ const NewItemPage = () => {
this.incrementCount('settings')}> - {this.state.count !== this.props.data.data.settings.length + {count !== selectedItem.settings.length ? variables.getMessage('marketplace:product.show_all') : variables.getMessage('marketplace:product.show_less')} @@ -221,8 +188,8 @@ const NewItemPage = () => { let languageNames = new Intl.DisplayNames([shortLocale], { type: 'language' }); let dateObj, formattedDate; - if (item.updated_at) { - dateObj = new Date(item.updated_at); + if (selectedItem.updated_at) { + dateObj = new Date(selectedItem.updated_at); formattedDate = new Intl.DateTimeFormat(shortLocale, { year: 'numeric', month: 'long', @@ -241,7 +208,7 @@ const NewItemPage = () => { onRequestClose={() => setShareModal(false)} > setShareModal(false)} /> @@ -267,18 +234,18 @@ const NewItemPage = () => { {moreInfoItem( , variables.getMessage('marketplace:product.created_by'), - item.author, + selectedItem.author, )} {itemWarning()}
- {/*{this.props.data.data.photos && ( + {selectedItem.photos && (
- +
)} - {this.props.data.data.settings && ( + {/*{selectedItem.settings && ( product { {variables.getMessage('marketplace:product.description')} - {item.description} + {selectedItem.description}
@@ -301,7 +268,7 @@ const NewItemPage = () => {
@@ -309,7 +276,7 @@ const NewItemPage = () => { className="icon" alt="icon" draggable={false} - src={item.icon_url} + src={selectedItem.icon_url} onError={(e) => { e.target.onerror = null; e.target.src = placeholderIcon; @@ -329,7 +296,7 @@ const NewItemPage = () => { )}

)} - {item.sideload !== true && ( + {selectedItem.sideload !== true && (
)} - {/*} - {this.props.data.data.in_collections?.length > 0 && ( + {selectedItem.in_collections?.length > 0 && (
@@ -364,18 +330,18 @@ const NewItemPage = () => { + /*onClick={() => this.props.toggleFunction( 'collection', - this.props.data.data.in_collections[0].name, + selectedItem.in_collections[0].name, ) - } + }*/ > - {this.props.data.data.in_collections[0].display_name} + {selectedItem.in_collections[0].display_name}
- )}*/} + )}
diff --git a/src/features/misc/views/Marketplace.jsx b/src/features/misc/views/Marketplace.jsx index 8ba726c0..7ea7fb62 100644 --- a/src/features/misc/views/Marketplace.jsx +++ b/src/features/misc/views/Marketplace.jsx @@ -1,94 +1,42 @@ -import variables from 'config/variables'; -import { memo, useState, useEffect } from 'react'; - +import { memo, useEffect } from 'react'; +import { useMarketData } from 'features/marketplace/api/MarketplaceDataContext'; import MarketplaceTab from '../../marketplace/views/Browse'; -import { sortItems } from '../../marketplace/api'; import { NewItems as Items } from '../../marketplace/components/Items/NewItems'; import { useTab } from 'components/Elements/MainModal/backend/TabContext'; import { NewItemPage } from '../../marketplace/views/newItemPage'; import { AnimatePresence, motion } from 'framer-motion'; function Marketplace(props) { - const [done, setDone] = useState(false); - const [items, setItems] = useState([]); - const [type, setType] = useState('all'); - const [selectedItem, setSelectedItem] = useState(null); + const { done, items, getItems } = useMarketData(); const { subTab } = useTab(); - const controller = new AbortController(); - - async function getItems() { - setDone(false); - const dataURL = - variables.constants.API_URL + - (type === 'collections' ? '/marketplace/collections' : '/marketplace/items/' + type); - - const { data } = await ( - await fetch(dataURL, { - signal: controller.signal, - }) - ).json(); - - if (controller.signal.aborted === true) { - return; - } - - setItems(sortItems(data, 'z-a')); - setDone(true); - } - useEffect(() => { if (navigator.onLine === false || localStorage.getItem('offlineMode') === 'true') { return; } - getItems(); }, []); return ( - { - /* props.changeTab(type)} current="marketplace" modalClose={props.modalClose}> -
- -
-
- -
-
- -
-
+ - -
-
- -
-
*/ - }, - ( - - - {subTab === '' ? ( - - - - ) : ( - - - - )} - - - ) + {subTab === '' ? ( + + + + ) : ( + + + + )} +
+ ); } diff --git a/src/i18n/en-GB/main.yml b/src/i18n/en-GB/main.yml index 6001e836..8c2fdc54 100644 --- a/src/i18n/en-GB/main.yml +++ b/src/i18n/en-GB/main.yml @@ -72,7 +72,7 @@ modals: file_upload_error: File is over 2MB navbar: settings: Settings - addons: Add-ons + addons: Library marketplace: Marketplace error_boundary: title: Error