Can now modify landing page. Fallback images for games and mods. Cached events. #29
26
index.html
26
index.html
@ -6,7 +6,10 @@
|
||||
|
||||
<!-- Open Graph Meta Tags -->
|
||||
<meta property="og:title" content="DEG Mods - Liberating Game Mods" />
|
||||
<meta property="og:description" content="Never get your game mods censored, get banned, lose your history, nor lose the connection between game mod creators and fans. Download your mods freely." />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="Never get your game mods censored, get banned, lose your history, nor lose the connection between game mod creators and fans. Download your mods freely."
|
||||
/>
|
||||
<meta property="og:image" content="/assets/img/DEGM%20Thumb.png" />
|
||||
<meta property="og:url" content="https://degmods.com" />
|
||||
<meta property="og:type" content="website" />
|
||||
@ -14,24 +17,33 @@
|
||||
<!-- Twitter Card Meta Tags -->
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content="DEG Mods - Liberating Game Mods" />
|
||||
<meta name="twitter:description" content="Never get your game mods censored, get banned, lose your history, nor lose the connection between game mod creators and fans. Download your mods freely." />
|
||||
<meta
|
||||
name="twitter:description"
|
||||
content="Never get your game mods censored, get banned, lose your history, nor lose the connection between game mod creators and fans. Download your mods freely."
|
||||
/>
|
||||
<meta name="twitter:image" content="/assets/img/DEGM%20Thumb.png" />
|
||||
|
||||
<!-- Other Meta Tags -->
|
||||
<meta name="description" content="Never get your game mods censored, get banned, lose your history, nor lose the connection between game mod creators and fans. Download your mods freely." />
|
||||
<meta
|
||||
name="description"
|
||||
content="Never get your game mods censored, get banned, lose your history, nor lose the connection between game mod creators and fans. Download your mods freely."
|
||||
/>
|
||||
|
||||
<!-- Links and Stylesheets -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/6.4.8/swiper-bundle.min.css" />
|
||||
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="/assets/fonts/fontawesome-all.min.css" />
|
||||
<link rel="icon" type="image/png" sizes="935x934" href="/assets/img/Logo%20with%20circle.png" />
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="935x934"
|
||||
href="/assets/img/Logo%20with%20circle.png"
|
||||
/>
|
||||
|
||||
<title>DEG Mods - Liberating Game Mods</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/6.4.8/swiper-bundle.min.js"></script>
|
||||
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
19
package-lock.json
generated
19
package-lock.json
generated
@ -34,6 +34,7 @@
|
||||
"react-router-dom": "^6.24.1",
|
||||
"react-toastify": "10.0.5",
|
||||
"react-window": "1.8.10",
|
||||
"swiper": "11.1.11",
|
||||
"uuid": "10.0.0",
|
||||
"webln": "0.3.2"
|
||||
},
|
||||
@ -4932,6 +4933,24 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/swiper": {
|
||||
"version": "11.1.11",
|
||||
"resolved": "https://registry.npmjs.org/swiper/-/swiper-11.1.11.tgz",
|
||||
"integrity": "sha512-077Aw3OrlZpkkBRf/6+44bGh/HZY/vsLEyate2db2KkJgYUIR5TvDgvvhcJtW/puXzw79w5KBc30DauEX6GZYQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/swiperjs"
|
||||
},
|
||||
{
|
||||
"type": "open_collective",
|
||||
"url": "http://opencollective.com/swiper"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 4.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/text-table": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||
|
@ -36,6 +36,7 @@
|
||||
"react-router-dom": "^6.24.1",
|
||||
"react-toastify": "10.0.5",
|
||||
"react-window": "1.8.10",
|
||||
"swiper": "11.1.11",
|
||||
"uuid": "10.0.0",
|
||||
"webln": "0.3.2"
|
||||
},
|
||||
|
@ -1,2 +1,37 @@
|
||||
export const T_TAG_VALUE = 'GameMod'
|
||||
export const MOD_FILTER_LIMIT = 20
|
||||
export const LANDING_PAGE_DATA = {
|
||||
featuredSlider: [
|
||||
'naddr1qvzqqqrkcgpzquuz5nxzzap2c034s8cuv5ayr7gjaxz7d22pgwfh0qpmsesy9eflqp4nxvp5xqer5den8qexzdrrvverzde5xfskxvm9xv6nsvtxx93nvdfnvy6rze3exyex2wfcx4jnvcfexscngveexvmnwwpsxd3rsd3kxq6ryef4xdnr5d3excenzvf5xgkkvdny8qkngveex5knjcnxxqkn2efnx3jrxvpcxgukxdggsmal6',
|
||||
'naddr1qvzqqqrkcgpzquuz5nxzzap2c034s8cuv5ayr7gjaxz7d22pgwfh0qpmsesy9eflqp4nxvp5xqer5den8qexzdrrvverzde5xfskxvm9xv6nsvtxx93nvdfnvy6rze3exyex2wfcx4jnvcfexscngveexvmnwwpsxd3rsd3kxq6ryef4xdnr5df5xccngvtrxqkkydpexukngvp4xgknsvp4vskkgdrxvgmkxdmp8quxycgx78rpf',
|
||||
'naddr1qvzqqqrkcgpzquuz5nxzzap2c034s8cuv5ayr7gjaxz7d22pgwfh0qpmsesy9eflqp4nxvp5xqer5den8qexzdrrvverzde5xfskxvm9xv6nsvtxx93nvdfnvy6rze3exyex2wfcx4jnvcfexscngveexvmnwwpsxd3rsd3kxq6ryef4xdnr5vrrvgmnjc33xuknwde4vskngvekxgknsenyxvkk2ctxvscrvenpvsmnxeqydygjx',
|
||||
'naddr1qvzqqqrkcgpzquuz5nxzzap2c034s8cuv5ayr7gjaxz7d22pgwfh0qpmsesy9eflqp4nxvp5xqer5den8qexzdrrvverzde5xfskxvm9xv6nsvtxx93nvdfnvy6rze3exyex2wfcx4jnvcfexscngveexvmnwwpsxd3rsd3kxq6ryef4xdnr5vf5x9nrxcekxvknjvmzxvkngcfsx5kkzcf3xqknsvmrvgenwe3j8p3nzwgka59vj'
|
||||
],
|
||||
awesomeMods: [
|
||||
'naddr1qvzqqqrkcgpzquuz5nxzzap2c034s8cuv5ayr7gjaxz7d22pgwfh0qpmsesy9eflqp4nxvp5xqer5den8qexzdrrvverzde5xfskxvm9xv6nsvtxx93nvdfnvy6rze3exyex2wfcx4jnvcfexscngveexvmnwwpsxd3rsd3kxq6ryef4xdnr5d3excenzvf5xgkkvdny8qkngveex5knjcnxxqkn2efnx3jrxvpcxgukxdggsmal6',
|
||||
'naddr1qvzqqqrkcgpzquuz5nxzzap2c034s8cuv5ayr7gjaxz7d22pgwfh0qpmsesy9eflqp4nxvp5xqer5den8qexzdrrvverzde5xfskxvm9xv6nsvtxx93nvdfnvy6rze3exyex2wfcx4jnvcfexscngveexvmnwwpsxd3rsd3kxq6ryef4xdnr5df5xccngvtrxqkkydpexukngvp4xgknsvp4vskkgdrxvgmkxdmp8quxycgx78rpf',
|
||||
'naddr1qvzqqqrkcgpzquuz5nxzzap2c034s8cuv5ayr7gjaxz7d22pgwfh0qpmsesy9eflqp4nxvp5xqer5den8qexzdrrvverzde5xfskxvm9xv6nsvtxx93nvdfnvy6rze3exyex2wfcx4jnvcfexscngveexvmnwwpsxd3rsd3kxq6ryef4xdnr5vrrvgmnjc33xuknwde4vskngvekxgknsenyxvkk2ctxvscrvenpvsmnxeqydygjx'
|
||||
],
|
||||
featuredGames: [
|
||||
{
|
||||
title: 'Immortal Guns',
|
||||
imageUrl: ''
|
||||
},
|
||||
{
|
||||
title: 'The Bounce House',
|
||||
imageUrl: ''
|
||||
},
|
||||
{
|
||||
title: 'Immortal Guns',
|
||||
imageUrl: ''
|
||||
},
|
||||
{
|
||||
title: 'Magenta Horizon Act 1',
|
||||
imageUrl: ''
|
||||
},
|
||||
{
|
||||
title: 'DEAD LETTER DEPT. Demo',
|
||||
imageUrl: ''
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -35,11 +35,26 @@ export const GamesPage = () => {
|
||||
</div>
|
||||
<div className='IBMSecMain IBMSMListWrapper'>
|
||||
<div className='IBMSMList IBMSMListFeaturedAlt'>
|
||||
<GameCard backgroundLink='/assets/img/DEGMods%20Placeholder%20Img.png' />
|
||||
<GameCard backgroundLink='/assets/img/DEGMods%20Placeholder%20Img.png' />
|
||||
<GameCard backgroundLink='/assets/img/DEGMods%20Placeholder%20Img.png' />
|
||||
<GameCard backgroundLink='/assets/img/DEGMods%20Placeholder%20Img.png' />
|
||||
<GameCard backgroundLink='/assets/img/DEGMods%20Placeholder%20Img.png' />
|
||||
<GameCard
|
||||
title='This is a game title, the best game title'
|
||||
imageUrl='/assets/img/DEGMods%20Placeholder%20Img.png'
|
||||
/>
|
||||
<GameCard
|
||||
title='This is a game title, the best game title'
|
||||
imageUrl='/assets/img/DEGMods%20Placeholder%20Img.png'
|
||||
/>
|
||||
<GameCard
|
||||
title='This is a game title, the best game title'
|
||||
imageUrl='/assets/img/DEGMods%20Placeholder%20Img.png'
|
||||
/>
|
||||
<GameCard
|
||||
title='This is a game title, the best game title'
|
||||
imageUrl='/assets/img/DEGMods%20Placeholder%20Img.png'
|
||||
/>
|
||||
<GameCard
|
||||
title='This is a game title, the best game title'
|
||||
imageUrl='/assets/img/DEGMods%20Placeholder%20Img.png'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className='IBMSecMain'>
|
||||
|
@ -1,123 +1,58 @@
|
||||
import { Filter, kinds, nip19 } from 'nostr-tools'
|
||||
import { useState } from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { A11y, Navigation, Pagination } from 'swiper/modules'
|
||||
import { Swiper, SwiperSlide } from 'swiper/react'
|
||||
import { BlogCard } from '../components/BlogCard'
|
||||
import { GameCard } from '../components/GameCard'
|
||||
import { ModCard } from '../components/ModCard'
|
||||
import { LANDING_PAGE_DATA } from '../constants'
|
||||
import { RelayController } from '../controllers'
|
||||
import { useDidMount } from '../hooks'
|
||||
import { appRoutes, getModsInnerPageRoute } from '../routes'
|
||||
import { ModDetails } from '../types'
|
||||
import {
|
||||
extractModData,
|
||||
fetchMods,
|
||||
handleModImageError,
|
||||
log,
|
||||
LogType
|
||||
} from '../utils'
|
||||
|
||||
import '../styles/cardLists.css'
|
||||
import '../styles/SimpleSlider.css'
|
||||
import '../styles/styles.css'
|
||||
|
||||
// Import Swiper styles
|
||||
import 'swiper/css'
|
||||
import 'swiper/css/navigation'
|
||||
import 'swiper/css/pagination'
|
||||
|
||||
export const HomePage = () => {
|
||||
const navigate = useNavigate()
|
||||
return (
|
||||
<div className='InnerBodyMain'>
|
||||
<div className='SliderWrapper'>
|
||||
<div className='ContainerMain'>
|
||||
<div className='IBMSecMain'>
|
||||
<div className='simple-slider IBMSMSlider'>
|
||||
<div className='swiper-container IBMSMSliderContainer'>
|
||||
<div className='swiper-wrapper IBMSMSliderContainerWrapper'>
|
||||
<div className='swiper-slide IBMSMSliderContainerWrapperSlider'>
|
||||
<div
|
||||
className='IBMSMSCWSPic'
|
||||
style={{
|
||||
background:
|
||||
'url("/assets/img/DEGMods%20Placeholder%20Img.png") center / cover no-repeat'
|
||||
}}
|
||||
></div>
|
||||
<div className='IBMSMSCWSInfo'>
|
||||
<h3 className='IBMSMSCWSInfoHeading'>Placeholder</h3>
|
||||
<p className='IBMSMSCWSInfoText'>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Integer nec odio. Praesent libero. Sed cursus ante
|
||||
dapibus diam. Sed nisi. Nulla quis sem at nibh elementum
|
||||
imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce
|
||||
nec tellus sed augue semper porta. Mauris massa.
|
||||
Vestibulum lacinia arcu eget nulla. className aptent
|
||||
taciti sociosqu ad litora torquent per conubia nostra,
|
||||
per inceptos himenaeos. Curabitur sodales ligula in
|
||||
libero.
|
||||
<br />
|
||||
</p>
|
||||
<div className='IBMSMSliderContainerWrapperSliderAction'>
|
||||
<a
|
||||
className='btn btnMain IBMSMSliderContainerWrapperSliderActionbtn'
|
||||
role='button'
|
||||
href='mods-inner.html'
|
||||
<Swiper
|
||||
className='swiper-container IBMSMSliderContainer'
|
||||
wrapperClass='swiper-wrapper IBMSMSliderContainerWrapper'
|
||||
modules={[Navigation, Pagination, A11y]}
|
||||
pagination={{ clickable: true, dynamicBullets: true }}
|
||||
slidesPerView={1}
|
||||
autoplay={{ delay: 5000 }}
|
||||
speed={1000}
|
||||
navigation
|
||||
loop
|
||||
>
|
||||
Check it out
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='swiper-slide IBMSMSliderContainerWrapperSlider'>
|
||||
<div
|
||||
className='IBMSMSCWSPic'
|
||||
style={{
|
||||
background:
|
||||
'url("/assets/img/DEGMods%20Placeholder%20Img.png") center / cover no-repeat'
|
||||
}}
|
||||
></div>
|
||||
<div className='IBMSMSCWSInfo'>
|
||||
<h3 className='IBMSMSCWSInfoHeading'>Placeholder</h3>
|
||||
<p className='IBMSMSCWSInfoText'>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Integer nec odio. Praesent libero. Sed cursus ante
|
||||
dapibus diam. Sed nisi. Nulla quis sem at nibh elementum
|
||||
imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce
|
||||
nec tellus sed augue semper porta. Mauris massa.
|
||||
Vestibulum lacinia arcu eget nulla. className aptent
|
||||
taciti sociosqu ad litora torquent per conubia nostra,
|
||||
per inceptos himenaeos. Curabitur sodales ligula in
|
||||
libero.
|
||||
<br />
|
||||
</p>
|
||||
<div className='IBMSMSliderContainerWrapperSliderAction'>
|
||||
<a
|
||||
className='btn btnMain IBMSMSliderContainerWrapperSliderActionbtn'
|
||||
role='button'
|
||||
href='mods-inner.html'
|
||||
>
|
||||
Check it out
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='swiper-slide IBMSMSliderContainerWrapperSlider'>
|
||||
<div
|
||||
className='IBMSMSCWSPic'
|
||||
style={{
|
||||
background:
|
||||
'url("/assets/img/DEGMods%20Placeholder%20Img.png") center / cover no-repeat'
|
||||
}}
|
||||
></div>
|
||||
<div className='IBMSMSCWSInfo'>
|
||||
<h3 className='IBMSMSCWSInfoHeading'>Placeholder</h3>
|
||||
<p className='IBMSMSCWSInfoText'>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Integer nec odio. Praesent libero. Sed cursus ante
|
||||
dapibus diam. Sed nisi. Nulla quis sem at nibh elementum
|
||||
imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce
|
||||
nec tellus sed augue semper porta. Mauris massa.
|
||||
Vestibulum lacinia arcu eget nulla. className aptent
|
||||
taciti sociosqu ad litora torquent per conubia nostra,
|
||||
per inceptos himenaeos. Curabitur sodales ligula in
|
||||
libero.
|
||||
<br />
|
||||
</p>
|
||||
<div className='IBMSMSliderContainerWrapperSliderAction'>
|
||||
<a
|
||||
className='btn btnMain IBMSMSliderContainerWrapperSliderActionbtn'
|
||||
role='button'
|
||||
href='mods-inner.html'
|
||||
>
|
||||
Check it out
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='swiper-pagination'></div>
|
||||
<div className='swiper-button-prev'></div>
|
||||
<div className='swiper-button-next'></div>
|
||||
</div>
|
||||
{LANDING_PAGE_DATA.featuredSlider.map((naddr) => (
|
||||
<SwiperSlide className='swiper-slide IBMSMSliderContainerWrapperSlider'>
|
||||
<SlideContent naddr={naddr} />
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -126,20 +61,18 @@ export const HomePage = () => {
|
||||
<div className='IBMSecMainGroup IBMSecMainGroupAlt'>
|
||||
<div className='IBMSecMain IBMSMListWrapper'>
|
||||
<div className='IBMSMTitleMain'>
|
||||
<h2 className='IBMSMTitleMainHeading'>Cool Games (WIP)</h2>
|
||||
<h2 className='IBMSMTitleMainHeading'>Cool Games</h2>
|
||||
</div>
|
||||
<div className='IBMSMList IBMSMListFeaturedAlt'>
|
||||
<GameCard backgroundLink='assets/img/DEGMods%20Placeholder%20Img.png' />
|
||||
<GameCard backgroundLink='assets/img/DEGMods%20Placeholder%20Img.png' />
|
||||
<GameCard backgroundLink='assets/img/DEGMods%20Placeholder%20Img.png' />
|
||||
<GameCard backgroundLink='assets/img/DEGMods%20Placeholder%20Img.png' />
|
||||
<GameCard backgroundLink='/assets/img/DEGMods%20Placeholder%20Img.png' />
|
||||
{LANDING_PAGE_DATA.featuredGames.map((game) => (
|
||||
<GameCard title={game.title} imageUrl={game.imageUrl} />
|
||||
))}
|
||||
</div>
|
||||
<div className='IBMSMAction'>
|
||||
<a
|
||||
className='btn btnMain IBMSMActionBtn'
|
||||
role='button'
|
||||
href='blog.html'
|
||||
onClick={() => navigate(appRoutes.games)}
|
||||
>
|
||||
View All
|
||||
</a>
|
||||
@ -147,114 +80,24 @@ export const HomePage = () => {
|
||||
</div>
|
||||
<div className='IBMSecMain IBMSMListWrapper'>
|
||||
<div className='IBMSMTitleMain'>
|
||||
<h2 className='IBMSMTitleMainHeading'>Awesome Mods (WIP)</h2>
|
||||
<h2 className='IBMSMTitleMainHeading'>Awesome Mods</h2>
|
||||
</div>
|
||||
<div className='IBMSMList IBMSMListAlt'>
|
||||
<ModCard
|
||||
title='Placeholder'
|
||||
summary='Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
|
||||
backgroundLink='/assets/img/DEGMods%20Placeholder%20Img.png'
|
||||
link=''
|
||||
handleClick={() => {
|
||||
alert(
|
||||
'these are dummy mods. So navigation on these are not implemented yet'
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<ModCard
|
||||
title='Placeholder'
|
||||
summary='Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
|
||||
backgroundLink='/assets/img/DEGMods%20Placeholder%20Img.png'
|
||||
link=''
|
||||
handleClick={() => {
|
||||
alert(
|
||||
'these are dummy mods. So navigation on these are not implemented yet'
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<ModCard
|
||||
title='Placeholder'
|
||||
summary='Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
|
||||
backgroundLink='/assets/img/DEGMods%20Placeholder%20Img.png'
|
||||
link=''
|
||||
handleClick={() => {
|
||||
alert(
|
||||
'these are dummy mods. So navigation on these are not implemented yet'
|
||||
)
|
||||
}}
|
||||
/>
|
||||
{LANDING_PAGE_DATA.awesomeMods.map((naddr) => (
|
||||
<DisplayMod key={naddr} naddr={naddr} />
|
||||
))}
|
||||
</div>
|
||||
<div className='IBMSMAction'>
|
||||
<a
|
||||
className='btn btnMain IBMSMActionBtn'
|
||||
role='button'
|
||||
href='blog.html'
|
||||
>
|
||||
View All
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className='IBMSecMain IBMSMListWrapper'>
|
||||
<div className='IBMSMTitleMain'>
|
||||
<h2 className='IBMSMTitleMainHeading'>Latest Mods (WIP)</h2>
|
||||
</div>
|
||||
<div className='IBMSMList'>
|
||||
<ModCard
|
||||
title='Placeholder'
|
||||
summary='Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
|
||||
backgroundLink='/assets/img/DEGMods%20Placeholder%20Img.png'
|
||||
link=''
|
||||
handleClick={() => {
|
||||
alert(
|
||||
'these are dummy mods. So navigation on these are not implemented yet'
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<ModCard
|
||||
title='Placeholder'
|
||||
summary='Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
|
||||
backgroundLink='/assets/img/DEGMods%20Placeholder%20Img.png'
|
||||
link=''
|
||||
handleClick={() => {
|
||||
alert(
|
||||
'these are dummy mods. So navigation on these are not implemented yet'
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<ModCard
|
||||
title='Placeholder'
|
||||
summary='Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
|
||||
backgroundLink='/assets/img/DEGMods%20Placeholder%20Img.png'
|
||||
link=''
|
||||
handleClick={() => {
|
||||
alert(
|
||||
'these are dummy mods. So navigation on these are not implemented yet'
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<ModCard
|
||||
title='Placeholder'
|
||||
summary='Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
|
||||
backgroundLink='/assets/img/DEGMods%20Placeholder%20Img.png'
|
||||
link=''
|
||||
handleClick={() => {
|
||||
alert(
|
||||
'these are dummy mods. So navigation on these are not implemented yet'
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='IBMSMAction'>
|
||||
<a
|
||||
className='btn btnMain IBMSMActionBtn'
|
||||
role='button'
|
||||
href='blog.html'
|
||||
onClick={() => navigate(appRoutes.mods)}
|
||||
>
|
||||
View All
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<DisplayLatestMods />
|
||||
<div className='IBMSecMain IBMSMListWrapper'>
|
||||
<div className='IBMSMTitleMain'>
|
||||
<h2 className='IBMSMTitleMainHeading'>Blog Posts (WIP)</h2>
|
||||
@ -281,3 +124,187 @@ export const HomePage = () => {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
type SlideContentProps = {
|
||||
naddr: string
|
||||
}
|
||||
|
||||
const SlideContent = ({ naddr }: SlideContentProps) => {
|
||||
const navigate = useNavigate()
|
||||
const [mod, setMod] = useState<ModDetails>()
|
||||
|
||||
useDidMount(() => {
|
||||
const decoded = nip19.decode<'naddr'>(naddr as `naddr1${string}`)
|
||||
const { identifier, kind, pubkey, relays = [] } = decoded.data
|
||||
|
||||
const filter: Filter = {
|
||||
'#a': [identifier],
|
||||
authors: [pubkey],
|
||||
kinds: [kind]
|
||||
}
|
||||
|
||||
RelayController.getInstance()
|
||||
.fetchEvent(filter, relays)
|
||||
.then((event) => {
|
||||
if (event) {
|
||||
const extracted = extractModData(event)
|
||||
setMod(extracted)
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
log(
|
||||
true,
|
||||
LogType.Error,
|
||||
'An error occurred in fetching mod details from relays',
|
||||
err
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
if (!mod) return <Spinner />
|
||||
|
||||
return (
|
||||
<>
|
||||
<img
|
||||
src={mod.featuredImageUrl}
|
||||
onError={handleModImageError}
|
||||
className='IBMSMSCWSPic'
|
||||
/>
|
||||
<div className='IBMSMSCWSInfo'>
|
||||
<h3 className='IBMSMSCWSInfoHeading'>{mod.title}</h3>
|
||||
<p className='IBMSMSCWSInfoText'>
|
||||
{mod.summary}
|
||||
<br />
|
||||
</p>
|
||||
<div className='IBMSMSliderContainerWrapperSliderAction'>
|
||||
<a
|
||||
className='btn btnMain IBMSMSliderContainerWrapperSliderActionbtn'
|
||||
role='button'
|
||||
onClick={() => navigate(getModsInnerPageRoute(naddr))}
|
||||
>
|
||||
Check it out
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
type DisplayModProps = {
|
||||
naddr: string
|
||||
}
|
||||
|
||||
const DisplayMod = ({ naddr }: DisplayModProps) => {
|
||||
const navigate = useNavigate()
|
||||
const [mod, setMod] = useState<ModDetails>()
|
||||
|
||||
useDidMount(() => {
|
||||
const decoded = nip19.decode<'naddr'>(naddr as `naddr1${string}`)
|
||||
const { identifier, kind, pubkey, relays = [] } = decoded.data
|
||||
|
||||
const filter: Filter = {
|
||||
'#a': [identifier],
|
||||
authors: [pubkey],
|
||||
kinds: [kind]
|
||||
}
|
||||
|
||||
RelayController.getInstance()
|
||||
.fetchEvent(filter, relays)
|
||||
.then((event) => {
|
||||
if (event) {
|
||||
const extracted = extractModData(event)
|
||||
setMod(extracted)
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
log(
|
||||
true,
|
||||
LogType.Error,
|
||||
'An error occurred in fetching mod details from relays',
|
||||
err
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
if (!mod) return <Spinner />
|
||||
|
||||
const route = getModsInnerPageRoute(naddr)
|
||||
|
||||
return (
|
||||
<ModCard
|
||||
title={mod.title}
|
||||
summary={mod.summary}
|
||||
imageUrl={mod.featuredImageUrl}
|
||||
link={`#${route}`}
|
||||
handleClick={() => navigate(route)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const DisplayLatestMods = () => {
|
||||
const navigate = useNavigate()
|
||||
const [isFetchingLatestMods, setIsFetchingLatestMods] = useState(true)
|
||||
const [latestMods, setLatestMods] = useState<ModDetails[]>([])
|
||||
|
||||
useDidMount(() => {
|
||||
fetchMods({ source: window.location.host, limit: 4 })
|
||||
.then((res) => {
|
||||
setLatestMods(res)
|
||||
})
|
||||
.finally(() => {
|
||||
setIsFetchingLatestMods(false)
|
||||
})
|
||||
})
|
||||
|
||||
return (
|
||||
<div className='IBMSecMain IBMSMListWrapper'>
|
||||
<div className='IBMSMTitleMain'>
|
||||
<h2 className='IBMSMTitleMainHeading'>Latest Mods</h2>
|
||||
</div>
|
||||
<div className='IBMSMList'>
|
||||
{isFetchingLatestMods ? (
|
||||
<Spinner />
|
||||
) : (
|
||||
latestMods.map((mod) => {
|
||||
const route = getModsInnerPageRoute(
|
||||
nip19.naddrEncode({
|
||||
identifier: mod.aTag,
|
||||
pubkey: mod.author,
|
||||
kind: kinds.ClassifiedListing
|
||||
})
|
||||
)
|
||||
|
||||
return (
|
||||
<ModCard
|
||||
key={mod.id}
|
||||
title={mod.title}
|
||||
summary={mod.summary}
|
||||
imageUrl={mod.featuredImageUrl}
|
||||
link={`#${route}`}
|
||||
handleClick={() => navigate(route)}
|
||||
/>
|
||||
)
|
||||
})
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className='IBMSMAction'>
|
||||
<a
|
||||
className='btn btnMain IBMSMActionBtn'
|
||||
role='button'
|
||||
onClick={() => navigate(appRoutes.mods)}
|
||||
>
|
||||
View All
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Spinner = () => {
|
||||
return (
|
||||
<div className='spinner'>
|
||||
<div className='spinnerCircle'></div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ export const ModsPage = () => {
|
||||
|
||||
useEffect(() => {
|
||||
setIsFetching(true)
|
||||
fetchMods(filterOptions.source)
|
||||
fetchMods({ source: filterOptions.source })
|
||||
.then((res) => {
|
||||
setMods(res)
|
||||
})
|
||||
@ -106,7 +106,10 @@ export const ModsPage = () => {
|
||||
const until =
|
||||
mods.length > 0 ? mods[mods.length - 1].published_at - 1 : undefined
|
||||
|
||||
fetchMods(filterOptions.source, until)
|
||||
fetchMods({
|
||||
source: filterOptions.source,
|
||||
until
|
||||
})
|
||||
.then((res) => {
|
||||
setMods(res)
|
||||
setPage((prev) => prev + 1)
|
||||
@ -121,7 +124,10 @@ export const ModsPage = () => {
|
||||
|
||||
const since = mods.length > 0 ? mods[0].published_at + 1 : undefined
|
||||
|
||||
fetchMods(filterOptions.source, undefined, since)
|
||||
fetchMods({
|
||||
source: filterOptions.source,
|
||||
since
|
||||
})
|
||||
.then((res) => {
|
||||
setMods(res)
|
||||
setPage((prev) => prev - 1)
|
||||
@ -215,7 +221,7 @@ export const ModsPage = () => {
|
||||
key={mod.id}
|
||||
title={mod.title}
|
||||
summary={mod.summary}
|
||||
backgroundLink={mod.featuredImageUrl}
|
||||
imageUrl={mod.featuredImageUrl}
|
||||
link={`#${route}`}
|
||||
handleClick={() => navigate(route)}
|
||||
/>
|
||||
|
@ -655,3 +655,28 @@ a:hover {
|
||||
|
||||
.errorMainText {
|
||||
}
|
||||
|
||||
.spinner {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.spinnerCircle {
|
||||
border: 4px solid #f3f3f3;
|
||||
border-top: 4px solid #3498db;
|
||||
border-radius: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
@ -134,6 +134,13 @@ export const initializeFormState = (
|
||||
]
|
||||
})
|
||||
|
||||
interface FetchModsOptions {
|
||||
source?: string
|
||||
until?: number
|
||||
since?: number
|
||||
limit?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a list of mods based on the provided source.
|
||||
*
|
||||
@ -144,15 +151,16 @@ export const initializeFormState = (
|
||||
* @returns A promise that resolves to an array of `ModDetails` objects. In case of an error,
|
||||
* it logs the error and shows a notification, then returns an empty array.
|
||||
*/
|
||||
export const fetchMods = async (
|
||||
source: string,
|
||||
until?: number,
|
||||
since?: number
|
||||
): Promise<ModDetails[]> => {
|
||||
export const fetchMods = async ({
|
||||
source,
|
||||
until,
|
||||
since,
|
||||
limit
|
||||
}: FetchModsOptions): Promise<ModDetails[]> => {
|
||||
// Define the filter criteria for fetching mods
|
||||
const filter: Filter = {
|
||||
kinds: [kinds.ClassifiedListing], // Specify the kind of events to fetch
|
||||
limit: MOD_FILTER_LIMIT, // Limit the number of events fetched to 20
|
||||
limit: limit || MOD_FILTER_LIMIT, // Limit the number of events fetched to 20
|
||||
'#t': [T_TAG_VALUE],
|
||||
until, // Optional filter to fetch events until this timestamp
|
||||
since // Optional filter to fetch events from this timestamp
|
||||
|
Loading…
Reference in New Issue
Block a user