mirror of
https://github.com/mue/mue.git
synced 2026-07-16 21:44:22 +02:00
Refactor ItemPage and related components for improved structure and readability
- Updated styles in _main.scss to enhance layout and visual consistency. - Refactored ItemPage.jsx to utilize new tab components (OverviewTab, QuotesTab, PhotosTab, PresetsTab) for better organization of content. - Created InfoItem and WarningBanner components for reusable UI elements. - Implemented QuotesTab and PhotosTab components to handle quotes and photos display logic. - Added PresetsTab component to manage settings display. - Enhanced user experience with dynamic tab switching and improved data handling.
This commit is contained in:
@@ -1,28 +1,26 @@
|
||||
import variables from 'config/variables';
|
||||
import { PureComponent, Fragment } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import {
|
||||
MdIosShare,
|
||||
MdFlag,
|
||||
MdAccountCircle,
|
||||
MdCalendarMonth,
|
||||
MdFormatQuote,
|
||||
MdImage,
|
||||
MdTranslate,
|
||||
MdOutlineWarning,
|
||||
MdStyle,
|
||||
} from 'react-icons/md';
|
||||
import { MdIosShare, MdFlag, MdAccountCircle } from 'react-icons/md';
|
||||
import Modal from 'react-modal';
|
||||
|
||||
import { Header } from 'components/Layout/Settings';
|
||||
import { Button } from 'components/Elements';
|
||||
|
||||
import { install, uninstall } from 'utils/marketplace';
|
||||
import { Carousel } from '../components/Elements/Carousel';
|
||||
import { ShareModal } from 'components/Elements';
|
||||
import placeholderIcon from 'assets/icons/marketplace-placeholder.png';
|
||||
import { Items } from '../components/Items/Items';
|
||||
|
||||
// Tab components
|
||||
import OverviewTab from './components/OverviewTab';
|
||||
import QuotesTab from './components/QuotesTab';
|
||||
import PhotosTab from './components/PhotosTab';
|
||||
import PresetsTab from './components/PresetsTab';
|
||||
|
||||
// Helper components
|
||||
import InfoItem from './components/InfoItem';
|
||||
import WarningBanner from './components/WarningBanner';
|
||||
|
||||
class ItemPage extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@@ -33,6 +31,7 @@ class ItemPage extends PureComponent {
|
||||
shareModal: false,
|
||||
count: 5,
|
||||
moreByCurator: [],
|
||||
activeTab: 'overview',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -63,11 +62,18 @@ class ItemPage extends PureComponent {
|
||||
}
|
||||
|
||||
incrementCount(type) {
|
||||
const newCount =
|
||||
this.state.count !== this.props.data.data[type].length
|
||||
? this.props.data.data[type].length
|
||||
: 5;
|
||||
const data = this.props.data.data;
|
||||
let length;
|
||||
|
||||
if (type === 'quotes' && Array.isArray(data.quotes)) {
|
||||
length = data.quotes.length;
|
||||
} else if (type === 'settings' && data.settings) {
|
||||
length = Object.keys(data.settings).length;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
const newCount = this.state.count !== length ? length : 5;
|
||||
this.setState({ count: newCount });
|
||||
}
|
||||
|
||||
@@ -84,18 +90,6 @@ class ItemPage extends PureComponent {
|
||||
const locale = localStorage.getItem('language');
|
||||
const shortLocale = locale.includes('_') ? locale.split('_')[0] : locale;
|
||||
const languageNames = new Intl.DisplayNames([shortLocale], { type: 'language' });
|
||||
const convertedType = (() => {
|
||||
const map = {
|
||||
photos: 'photo_packs',
|
||||
quotes: 'quote_packs',
|
||||
settings: 'preset_settings',
|
||||
};
|
||||
return map[this.props.data.data.type];
|
||||
})();
|
||||
const moreByCurator = this.state.moreByCurator
|
||||
.filter((item) => item.type === convertedType && item.name !== this.props.data.data.name)
|
||||
.sort(() => 0.5 - Math.random())
|
||||
.slice(0, 3);
|
||||
|
||||
// Extract colour from data (British spelling as used in API)
|
||||
const mainColor = this.props.data.data.colour;
|
||||
@@ -117,6 +111,25 @@ class ItemPage extends PureComponent {
|
||||
const isLight = isLightColor(mainColor);
|
||||
const textColor = isLight ? '#000000' : '#ffffff';
|
||||
|
||||
const { activeTab } = this.state;
|
||||
const quotes = Array.isArray(this.props.data.data.quotes) ? this.props.data.data.quotes : [];
|
||||
const photos = Array.isArray(this.props.data.data.photos) ? this.props.data.data.photos : [];
|
||||
const settings = this.props.data.data.settings;
|
||||
const hasPhotos = photos.length > 0;
|
||||
const hasQuotes = quotes.length > 0;
|
||||
const hasSettings = !!settings;
|
||||
|
||||
// Format date for details section
|
||||
let formattedDate = '';
|
||||
if (this.props.data.data.updated_at) {
|
||||
const dateObj = new Date(this.props.data.data.updated_at);
|
||||
formattedDate = new Intl.DateTimeFormat(shortLocale, {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: '2-digit',
|
||||
}).format(dateObj);
|
||||
}
|
||||
|
||||
// Create dynamic styles for theming with the main color
|
||||
const themedStyles = mainColor ? (
|
||||
<style>{`
|
||||
@@ -190,12 +203,6 @@ class ItemPage extends PureComponent {
|
||||
return null;
|
||||
}
|
||||
|
||||
// prevent console error
|
||||
let iconsrc = this.props.data.icon;
|
||||
if (!this.props.data.icon) {
|
||||
iconsrc = null;
|
||||
}
|
||||
|
||||
let updateButton;
|
||||
if (this.state.showUpdateButton) {
|
||||
updateButton = (
|
||||
@@ -209,52 +216,10 @@ class ItemPage extends PureComponent {
|
||||
);
|
||||
}
|
||||
|
||||
const itemWarning = () => {
|
||||
const template = (message) => (
|
||||
<div className="itemWarning">
|
||||
<MdOutlineWarning />
|
||||
<div className="text">
|
||||
<span className="header">Warning</span>
|
||||
<span>{message}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (this.props.data.data.sideload === true) {
|
||||
return template(variables.getMessage('modals.main.marketplace.product.sideload_warning'));
|
||||
}
|
||||
|
||||
if (this.props.data.data.image_api === true) {
|
||||
return template(variables.getMessage('modals.main.marketplace.product.third_party_api'));
|
||||
}
|
||||
|
||||
if (this.props.data.data.language !== undefined && this.props.data.data.language !== null) {
|
||||
if (shortLocale !== this.props.data.data.language) {
|
||||
return template(variables.getMessage('modals.main.marketplace.product.not_in_language'));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const moreInfoItem = (icon, header, text) => (
|
||||
<div className="infoItem">
|
||||
{icon}
|
||||
<div className="text">
|
||||
<span className="header">{header}</span>
|
||||
<span>{text}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
let dateObj, formattedDate;
|
||||
if (this.props.data.data.updated_at) {
|
||||
dateObj = new Date(this.props.data.data.updated_at);
|
||||
formattedDate = new Intl.DateTimeFormat(shortLocale, {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: '2-digit',
|
||||
}).format(dateObj);
|
||||
// prevent console error
|
||||
let iconsrc = this.props.data.icon;
|
||||
if (!this.props.data.icon) {
|
||||
iconsrc = null;
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -291,135 +256,7 @@ class ItemPage extends PureComponent {
|
||||
goBack={this.props.toggleFunction}
|
||||
/> */}
|
||||
<div className="itemPage">
|
||||
<div className="itemShowcase">
|
||||
<div className="subHeader">
|
||||
{moreInfoItem(
|
||||
<MdAccountCircle />,
|
||||
variables.getMessage('modals.main.marketplace.product.created_by'),
|
||||
this.props.data.author,
|
||||
)}
|
||||
{itemWarning()}
|
||||
</div>
|
||||
{this.props.data.data.photos && (
|
||||
<div className="carousel">
|
||||
<div className="carousel_container">
|
||||
<Carousel data={this.props.data.data.photos} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{this.props.data.data.settings && (
|
||||
<img
|
||||
alt="product"
|
||||
draggable={false}
|
||||
src={iconsrc}
|
||||
onError={(e) => {
|
||||
e.target.onerror = null;
|
||||
e.target.src = placeholderIcon;
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<div className="marketplaceDescription">
|
||||
<span className="title">
|
||||
{variables.getMessage('modals.main.marketplace.product.description')}
|
||||
</span>
|
||||
<span
|
||||
className="subtitle"
|
||||
dangerouslySetInnerHTML={{ __html: this.props.data.description }}
|
||||
/>
|
||||
</div>
|
||||
{this.props.data.data.quotes && (
|
||||
<>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{variables.getMessage('modals.main.settings.sections.quote.title')}</th>
|
||||
<th>{variables.getMessage('modals.main.settings.sections.quote.author')}</th>
|
||||
</tr>
|
||||
{this.props.data.data.quotes.slice(0, this.state.count).map((quote, index) => (
|
||||
<tr key={index}>
|
||||
<td>{quote.quote}</td>
|
||||
<td>{quote.author}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="showMoreItems">
|
||||
<span className="link" onClick={() => this.incrementCount('quotes')}>
|
||||
{this.state.count !== this.props.data.data.quotes.length
|
||||
? variables.getMessage('modals.main.marketplace.product.show_all')
|
||||
: variables.getMessage('modals.main.marketplace.product.show_less')}
|
||||
</span>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{this.props.data.data.settings && (
|
||||
<>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{variables.getMessage('modals.main.marketplace.product.setting')}</th>
|
||||
<th>{variables.getMessage('modals.main.marketplace.product.value')}</th>
|
||||
</tr>
|
||||
{Object.entries(this.props.data.data.settings)
|
||||
.slice(0, this.state.count)
|
||||
.map(([key, value]) => (
|
||||
<tr key={key}>
|
||||
<td>{key}</td>
|
||||
<td>{value}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="showMoreItems">
|
||||
<span className="link" onClick={() => this.incrementCount('settings')}>
|
||||
{this.state.count !== this.props.data.data.settings.length
|
||||
? variables.getMessage('modals.main.marketplace.product.show_all')
|
||||
: variables.getMessage('modals.main.marketplace.product.show_less')}
|
||||
</span>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div className="marketplaceDescription">
|
||||
<span className="title">
|
||||
{variables.getMessage('modals.main.marketplace.product.details')}
|
||||
</span>
|
||||
<div className="moreInfo">
|
||||
{this.props.data.data.updated_at &&
|
||||
moreInfoItem(
|
||||
<MdCalendarMonth />,
|
||||
variables.getMessage('modals.main.marketplace.product.updated_at'),
|
||||
formattedDate,
|
||||
)}
|
||||
{this.props.data.data.quotes &&
|
||||
moreInfoItem(
|
||||
<MdFormatQuote />,
|
||||
variables.getMessage('modals.main.marketplace.product.no_quotes'),
|
||||
this.props.data.data.quotes.length,
|
||||
)}
|
||||
{this.props.data.data.photos &&
|
||||
moreInfoItem(
|
||||
<MdImage />,
|
||||
variables.getMessage('modals.main.marketplace.product.no_images'),
|
||||
this.props.data.data.photos.length,
|
||||
)}
|
||||
{this.props.data.data.quotes && this.props.data.data.language
|
||||
? moreInfoItem(
|
||||
<MdTranslate />,
|
||||
variables.getMessage('modals.main.settings.sections.language.title'),
|
||||
languageNames.of(this.props.data.data.language),
|
||||
)
|
||||
: null}
|
||||
{moreInfoItem(
|
||||
<MdStyle />,
|
||||
variables.getMessage('modals.main.settings.sections.background.type.title'),
|
||||
variables.getMessage(
|
||||
'modals.main.marketplace.' + this.getName(this.props.data.data.type),
|
||||
) || 'marketplace',
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="itemInfo">
|
||||
<aside className="itemInfo">
|
||||
<div className="front">
|
||||
<img
|
||||
className="icon"
|
||||
@@ -432,7 +269,10 @@ class ItemPage extends PureComponent {
|
||||
}}
|
||||
/>
|
||||
{localStorage.getItem('welcomePreview') !== 'true' ? (
|
||||
this.props.button
|
||||
<>
|
||||
{this.props.button}
|
||||
{updateButton}
|
||||
</>
|
||||
) : (
|
||||
<p style={{ textAlign: 'center' }}>
|
||||
{variables.getMessage(
|
||||
@@ -470,26 +310,106 @@ class ItemPage extends PureComponent {
|
||||
</>
|
||||
)}
|
||||
{this.props.data.data.in_collections?.length > 0 && (
|
||||
<div>
|
||||
<div className="inCollection">
|
||||
<span className="subtitle">
|
||||
{variables.getMessage('modals.main.marketplace.product.part_of')}
|
||||
</span>
|
||||
<span
|
||||
className="title"
|
||||
onClick={() =>
|
||||
this.props.toggleFunction(
|
||||
'collection',
|
||||
this.props.data.data.in_collections[0].name,
|
||||
)
|
||||
}
|
||||
>
|
||||
{this.props.data.data.in_collections[0].display_name}
|
||||
</span>
|
||||
</div>
|
||||
<div className="inCollection">
|
||||
<span className="subtitle">
|
||||
{variables.getMessage('modals.main.marketplace.product.part_of')}
|
||||
</span>
|
||||
<span
|
||||
className="title"
|
||||
onClick={() =>
|
||||
this.props.toggleFunction(
|
||||
'collection',
|
||||
this.props.data.data.in_collections[0].name,
|
||||
)
|
||||
}
|
||||
>
|
||||
{this.props.data.data.in_collections[0].display_name}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</aside>
|
||||
<div className="itemContent">
|
||||
<div className="itemTop">
|
||||
<div className="subHeader">
|
||||
<InfoItem
|
||||
icon={<MdAccountCircle />}
|
||||
header={variables.getMessage('modals.main.marketplace.product.created_by')}
|
||||
text={this.props.data.author}
|
||||
/>
|
||||
<WarningBanner data={this.props.data.data} shortLocale={shortLocale} />
|
||||
</div>
|
||||
<div className="itemTabs">
|
||||
<button
|
||||
type="button"
|
||||
className={`itemTab ${activeTab === 'overview' ? 'active' : ''}`}
|
||||
onClick={() => this.setState({ activeTab: 'overview' })}
|
||||
>
|
||||
{variables.getMessage('modals.main.marketplace.product.overview_tab') ||
|
||||
'Overview'}
|
||||
</button>
|
||||
{hasQuotes && (
|
||||
<button
|
||||
type="button"
|
||||
className={`itemTab ${activeTab === 'quotes' ? 'active' : ''}`}
|
||||
onClick={() => this.setState({ activeTab: 'quotes' })}
|
||||
>
|
||||
{variables.getMessage('modals.main.marketplace.product.quotes_tab') || 'Quotes'}
|
||||
</button>
|
||||
)}
|
||||
|
||||
{hasPhotos && (
|
||||
<button
|
||||
type="button"
|
||||
className={`itemTab ${activeTab === 'photos' ? 'active' : ''}`}
|
||||
onClick={() => this.setState({ activeTab: 'photos' })}
|
||||
>
|
||||
{variables.getMessage('modals.main.marketplace.product.photos_tab') || 'Photos'}
|
||||
</button>
|
||||
)}
|
||||
|
||||
{hasSettings && (
|
||||
<button
|
||||
type="button"
|
||||
className={`itemTab ${activeTab === 'presets' ? 'active' : ''}`}
|
||||
onClick={() => this.setState({ activeTab: 'presets' })}
|
||||
>
|
||||
{variables.getMessage('modals.main.marketplace.product.presets_tab') ||
|
||||
'Presets'}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="tabContent">
|
||||
{activeTab === 'overview' && (
|
||||
<OverviewTab
|
||||
data={this.props.data.data}
|
||||
description={this.props.data.description}
|
||||
iconsrc={iconsrc}
|
||||
shortLocale={shortLocale}
|
||||
languageNames={languageNames}
|
||||
formattedDate={formattedDate}
|
||||
getName={this.getName}
|
||||
count={this.state.count}
|
||||
onIncrementCount={(type) => this.incrementCount(type)}
|
||||
/>
|
||||
)}
|
||||
{activeTab === 'quotes' && hasQuotes && (
|
||||
<QuotesTab
|
||||
quotes={quotes}
|
||||
count={this.state.count}
|
||||
onIncrementCount={(type) => this.incrementCount(type)}
|
||||
/>
|
||||
)}
|
||||
{activeTab === 'photos' && hasPhotos && <PhotosTab photos={photos} />}
|
||||
{activeTab === 'presets' && hasSettings && (
|
||||
<PresetsTab
|
||||
settings={settings}
|
||||
count={this.state.count}
|
||||
onIncrementCount={(type) => this.incrementCount(type)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* {moreByCurator.length > 1 && (
|
||||
|
||||
11
src/features/marketplace/views/components/InfoItem.jsx
Normal file
11
src/features/marketplace/views/components/InfoItem.jsx
Normal file
@@ -0,0 +1,11 @@
|
||||
const InfoItem = ({ icon, header, text }) => (
|
||||
<div className="infoItem">
|
||||
{icon}
|
||||
<div className="text">
|
||||
<span className="header">{header}</span>
|
||||
<span>{text}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default InfoItem;
|
||||
134
src/features/marketplace/views/components/OverviewTab.jsx
Normal file
134
src/features/marketplace/views/components/OverviewTab.jsx
Normal file
@@ -0,0 +1,134 @@
|
||||
import variables from 'config/variables';
|
||||
import { MdCalendarMonth, MdFormatQuote, MdImage, MdTranslate, MdStyle } from 'react-icons/md';
|
||||
import { Carousel } from '../../components/Elements/Carousel';
|
||||
import placeholderIcon from 'assets/icons/marketplace-placeholder.png';
|
||||
import InfoItem from './InfoItem';
|
||||
|
||||
const OverviewTab = ({
|
||||
data,
|
||||
description,
|
||||
iconsrc,
|
||||
shortLocale,
|
||||
languageNames,
|
||||
formattedDate,
|
||||
getName,
|
||||
count,
|
||||
onIncrementCount,
|
||||
}) => {
|
||||
const quotes = Array.isArray(data.quotes) ? data.quotes : [];
|
||||
const photos = Array.isArray(data.photos) ? data.photos : [];
|
||||
const hasPhotos = photos.length > 0;
|
||||
const hasQuotes = quotes.length > 0;
|
||||
const hasSettings = data.settings;
|
||||
|
||||
// Quote statistics
|
||||
const totalQuotes = hasQuotes ? quotes.length : 0;
|
||||
const uniqueAuthorsCount = hasQuotes ? new Set(quotes.map((quote) => quote.author)).size : 0;
|
||||
const averageCharacters = hasQuotes
|
||||
? Math.round(
|
||||
quotes.reduce(
|
||||
(accumulator, quote) => accumulator + (quote.quote ? quote.quote.length : 0),
|
||||
0,
|
||||
) / quotes.length,
|
||||
)
|
||||
: 0;
|
||||
|
||||
const totalQuotesLabel =
|
||||
variables.getMessage('modals.main.marketplace.product.no_quotes') || 'Total quotes';
|
||||
const uniqueAuthorsLabel =
|
||||
variables.getMessage('modals.main.marketplace.product.unique_authors') || 'Unique authors';
|
||||
const averageCharactersLabel =
|
||||
variables.getMessage('modals.main.marketplace.product.average_characters') || 'Avg. characters';
|
||||
|
||||
const formatNumber = (value) =>
|
||||
typeof value === 'number' ? value.toLocaleString(shortLocale) : value;
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Preview image for settings presets */}
|
||||
{hasSettings && (
|
||||
<img
|
||||
alt="product"
|
||||
draggable={false}
|
||||
src={iconsrc}
|
||||
onError={(e) => {
|
||||
e.target.onerror = null;
|
||||
e.target.src = placeholderIcon;
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Description */}
|
||||
<div className="marketplaceDescription">
|
||||
<span className="title">
|
||||
{variables.getMessage('modals.main.marketplace.product.description')}
|
||||
</span>
|
||||
<span className="subtitle" dangerouslySetInnerHTML={{ __html: description }} />
|
||||
</div>
|
||||
|
||||
{/* Quote pack statistics */}
|
||||
{hasQuotes && (
|
||||
<div className="itemHighlights">
|
||||
<div className="highlightCard">
|
||||
<span className="highlightLabel">{totalQuotesLabel}</span>
|
||||
<span className="highlightValue">{formatNumber(totalQuotes)}</span>
|
||||
</div>
|
||||
<div className="highlightCard">
|
||||
<span className="highlightLabel">{uniqueAuthorsLabel}</span>
|
||||
<span className="highlightValue">{formatNumber(uniqueAuthorsCount)}</span>
|
||||
</div>
|
||||
<div className="highlightCard">
|
||||
<span className="highlightLabel">{averageCharactersLabel}</span>
|
||||
<span className="highlightValue">{formatNumber(averageCharacters)}</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Details section */}
|
||||
<div className="marketplaceDescription marketplaceDetails">
|
||||
<span className="title">
|
||||
{variables.getMessage('modals.main.marketplace.product.details')}
|
||||
</span>
|
||||
<div className="moreInfo">
|
||||
{data.updated_at && (
|
||||
<InfoItem
|
||||
icon={<MdCalendarMonth />}
|
||||
header={variables.getMessage('modals.main.marketplace.product.updated_at')}
|
||||
text={formattedDate}
|
||||
/>
|
||||
)}
|
||||
{hasQuotes && (
|
||||
<InfoItem
|
||||
icon={<MdFormatQuote />}
|
||||
header={variables.getMessage('modals.main.marketplace.product.no_quotes')}
|
||||
text={quotes.length}
|
||||
/>
|
||||
)}
|
||||
{hasPhotos && (
|
||||
<InfoItem
|
||||
icon={<MdImage />}
|
||||
header={variables.getMessage('modals.main.marketplace.product.no_images')}
|
||||
text={photos.length}
|
||||
/>
|
||||
)}
|
||||
{hasQuotes && data.language && (
|
||||
<InfoItem
|
||||
icon={<MdTranslate />}
|
||||
header={variables.getMessage('modals.main.settings.sections.language.title')}
|
||||
text={languageNames.of(data.language)}
|
||||
/>
|
||||
)}
|
||||
<InfoItem
|
||||
icon={<MdStyle />}
|
||||
header={variables.getMessage('modals.main.settings.sections.background.type.title')}
|
||||
text={
|
||||
variables.getMessage('modals.main.marketplace.' + getName(data.type)) || 'marketplace'
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default OverviewTab;
|
||||
13
src/features/marketplace/views/components/PhotosTab.jsx
Normal file
13
src/features/marketplace/views/components/PhotosTab.jsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Carousel } from '../../components/Elements/Carousel';
|
||||
|
||||
const PhotosTab = ({ photos }) => {
|
||||
return (
|
||||
<div className="carousel">
|
||||
<div className="carousel_container">
|
||||
<Carousel data={photos} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PhotosTab;
|
||||
33
src/features/marketplace/views/components/PresetsTab.jsx
Normal file
33
src/features/marketplace/views/components/PresetsTab.jsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import variables from 'config/variables';
|
||||
|
||||
const PresetsTab = ({ settings, count, onIncrementCount }) => {
|
||||
return (
|
||||
<>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{variables.getMessage('modals.main.marketplace.product.setting')}</th>
|
||||
<th>{variables.getMessage('modals.main.marketplace.product.value')}</th>
|
||||
</tr>
|
||||
{Object.entries(settings)
|
||||
.slice(0, count)
|
||||
.map(([key, value]) => (
|
||||
<tr key={key}>
|
||||
<td>{key}</td>
|
||||
<td>{value}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="showMoreItems">
|
||||
<span className="link" onClick={() => onIncrementCount('settings')}>
|
||||
{count !== Object.keys(settings).length
|
||||
? variables.getMessage('modals.main.marketplace.product.show_all')
|
||||
: variables.getMessage('modals.main.marketplace.product.show_less')}
|
||||
</span>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PresetsTab;
|
||||
31
src/features/marketplace/views/components/QuotesTab.jsx
Normal file
31
src/features/marketplace/views/components/QuotesTab.jsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import variables from 'config/variables';
|
||||
|
||||
const QuotesTab = ({ quotes, count, onIncrementCount }) => {
|
||||
return (
|
||||
<>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{variables.getMessage('modals.main.settings.sections.quote.title')}</th>
|
||||
<th>{variables.getMessage('modals.main.settings.sections.quote.author')}</th>
|
||||
</tr>
|
||||
{quotes.slice(0, count).map((quote, index) => (
|
||||
<tr key={index}>
|
||||
<td>{quote.quote}</td>
|
||||
<td>{quote.author}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="showMoreItems">
|
||||
<span className="link" onClick={() => onIncrementCount('quotes')}>
|
||||
{count !== quotes.length
|
||||
? variables.getMessage('modals.main.marketplace.product.show_all')
|
||||
: variables.getMessage('modals.main.marketplace.product.show_less')}
|
||||
</span>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default QuotesTab;
|
||||
32
src/features/marketplace/views/components/WarningBanner.jsx
Normal file
32
src/features/marketplace/views/components/WarningBanner.jsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import variables from 'config/variables';
|
||||
import { MdOutlineWarning } from 'react-icons/md';
|
||||
|
||||
const WarningBanner = ({ data, shortLocale }) => {
|
||||
const template = (message) => (
|
||||
<div className="itemWarning">
|
||||
<MdOutlineWarning />
|
||||
<div className="text">
|
||||
<span className="header">Warning</span>
|
||||
<span>{message}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (data.sideload === true) {
|
||||
return template(variables.getMessage('modals.main.marketplace.product.sideload_warning'));
|
||||
}
|
||||
|
||||
if (data.image_api === true) {
|
||||
return template(variables.getMessage('modals.main.marketplace.product.third_party_api'));
|
||||
}
|
||||
|
||||
if (data.language !== undefined && data.language !== null) {
|
||||
if (shortLocale !== data.language) {
|
||||
return template(variables.getMessage('modals.main.marketplace.product.not_in_language'));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export default WarningBanner;
|
||||
9
src/features/marketplace/views/components/index.js
Normal file
9
src/features/marketplace/views/components/index.js
Normal file
@@ -0,0 +1,9 @@
|
||||
// Tab components
|
||||
export { default as OverviewTab } from './OverviewTab';
|
||||
export { default as QuotesTab } from './QuotesTab';
|
||||
export { default as PhotosTab } from './PhotosTab';
|
||||
export { default as PresetsTab } from './PresetsTab';
|
||||
|
||||
// Helper components
|
||||
export { default as InfoItem } from './InfoItem';
|
||||
export { default as WarningBanner } from './WarningBanner';
|
||||
Reference in New Issue
Block a user