generated from shuding/nextra-docs-template
-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e0e5a03
commit 4a69db2
Showing
12 changed files
with
359 additions
and
236 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,85 @@ | ||
import { useEffect, useState } from 'react' | ||
import { EcosystemSection, EcosystemSkeleton } from '.' | ||
import { | ||
EcosystemResponse, | ||
getSeiEcosystemAppsData, | ||
} from '../../data/ecosystemData' | ||
|
||
const EcosystemDynamicSection = ({ category }: { category: string }) => { | ||
const [apps, setApps] = useState<EcosystemResponse['data'] | null>(null) | ||
const [loading, setLoading] = useState(true) | ||
|
||
useEffect(() => { | ||
const fetchData = async () => { | ||
await getSeiEcosystemAppsData() | ||
.then((data) => { | ||
setApps(data.data) | ||
setLoading(false) | ||
}) | ||
.catch((error) => { | ||
console.error('Failed to fetch data:', error) | ||
}) | ||
.finally(() => { | ||
setLoading(false) | ||
}) | ||
} | ||
fetchData() | ||
}, []) | ||
|
||
if (!apps || loading) return <EcosystemSkeleton /> | ||
|
||
// filter out apps that don't have a categorie | ||
const filteredApps = apps.filter((app) => app.fieldData.categorie !== undefined && app.fieldData['categorie-2'] !== undefined); | ||
|
||
const appsByCategory = (category: string) => | ||
filteredApps.filter((app) => app.fieldData.categorie === category) | ||
return <EcosystemSection apps={appsByCategory(category)} /> | ||
import { useEffect, useState } from 'react'; | ||
import { groupBy } from 'underscore'; | ||
import { EcosystemSection, EcosystemSkeleton } from '.'; | ||
import { EcosystemItem, EcosystemResponse, getSeiEcosystemAppsData } from '../../data/ecosystemData'; | ||
|
||
interface EcosystemDynamicSectionProps { | ||
category: string; | ||
searchTerm: string | undefined; | ||
} | ||
|
||
export default EcosystemDynamicSection | ||
export default function EcosystemDynamicSection({ category, searchTerm }: EcosystemDynamicSectionProps) { | ||
const [apps, setApps] = useState<EcosystemItem[] | null>(null); | ||
const [loading, setLoading] = useState(true); | ||
const [activeSubCat, setActiveSubCat] = useState<string | null>(null); | ||
|
||
useEffect(() => { | ||
(async () => { | ||
try { | ||
const data: EcosystemResponse = await getSeiEcosystemAppsData(); | ||
setApps(data.data); | ||
} catch (err) { | ||
console.error('Failed to fetch data:', err); | ||
} finally { | ||
setLoading(false); | ||
} | ||
})(); | ||
}, []); | ||
|
||
let subCats: string[] = []; | ||
let grouped: Record<string, EcosystemItem[]> = {}; | ||
|
||
if (apps) { | ||
const catLower = category.toLowerCase(); | ||
const categoryApps = apps.filter((app) => (app.fieldData.categorie?.toLowerCase() || '') === catLower); | ||
const normSearch = (searchTerm ?? '').toLowerCase(); | ||
const filtered = categoryApps.filter((app) => { | ||
if (!normSearch) return true; | ||
const name = app.fieldData.name?.toLowerCase() || ''; | ||
const subCat = app.fieldData['categorie-2']?.toLowerCase() || ''; | ||
return name.includes(normSearch) || subCat.includes(normSearch); | ||
}); | ||
grouped = groupBy(filtered, (a) => a.fieldData['categorie-2'] || 'Other'); | ||
subCats = Object.keys(grouped).sort(); | ||
} | ||
|
||
useEffect(() => { | ||
if (!apps) return; | ||
if (!activeSubCat && subCats.length > 0) { | ||
setActiveSubCat(subCats[0]); | ||
} else if (activeSubCat && !grouped[activeSubCat]) { | ||
setActiveSubCat(subCats[0] ?? null); | ||
} | ||
}, [apps, subCats, activeSubCat, grouped]); | ||
|
||
if (loading) { | ||
return <EcosystemSkeleton />; | ||
} | ||
|
||
if (!apps) { | ||
return <EcosystemSkeleton />; | ||
} | ||
|
||
const activeApps = activeSubCat && grouped[activeSubCat] ? grouped[activeSubCat] : []; | ||
|
||
return ( | ||
<div className='mt-4'> | ||
<div className='flex gap-4 overflow-x-auto pb-2 mb-4'> | ||
{subCats.map((sc) => { | ||
const isActive = sc === activeSubCat; | ||
return ( | ||
<button | ||
key={sc} | ||
onClick={() => setActiveSubCat(sc)} | ||
className={`whitespace-nowrap px-3 py-1 rounded-sm text-sm font-medium transition-colors ${ | ||
isActive ? 'bg-gray-700 text-white' : 'bg-gray-800 text-gray-200 hover:bg-gray-700' | ||
}`}> | ||
{sc} | ||
</button> | ||
); | ||
})} | ||
</div> | ||
<EcosystemSection apps={activeApps} /> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import React from 'react'; | ||
|
||
interface EcosystemHeaderProps { | ||
searchTerm: string; | ||
setSearchTerm: (val: string) => void; | ||
} | ||
|
||
export default function EcosystemHeader({ searchTerm, setSearchTerm }: EcosystemHeaderProps) { | ||
return ( | ||
<div className='bg-black text-white px-6 py-10'> | ||
<h1 className='text-4xl font-bold'>Sei Ecosystem Map</h1> | ||
<p className='mt-2 max-w-2xl text-gray-300'> | ||
Sei Ecosystem is the epicenter of technological advancement, bringing together creative minds and industry leaders to drive the future of Sei’s blockchain | ||
technology. | ||
</p> | ||
<div className='mt-6 flex flex-wrap gap-4'> | ||
<a | ||
href='/' | ||
className='inline-flex items-center justify-center rounded-md border-2 border-white px-4 py-2 text-white hover:bg-white hover:text-black transition-colors'> | ||
Start Building | ||
</a> | ||
<a | ||
href='https://sei-forms.typeform.com/join-ecosystem?typeform-source=p12rt1ecint.typeform.com' | ||
target='_blank' | ||
rel='noopener noreferrer' | ||
className='inline-flex items-center justify-center rounded-md border-2 border-white px-4 py-2 text-white hover:bg-white hover:text-black transition-colors'> | ||
Join the Ecosystem | ||
</a> | ||
</div> | ||
<div className='mt-8 max-w-md'> | ||
<input | ||
type='search' | ||
placeholder='Search for apps...' | ||
value={searchTerm} | ||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSearchTerm(e.target.value)} | ||
className='w-full px-4 py-2 bg-black text-white border-2 border-red-600 rounded-md placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-red-600 focus:ring-offset-2 focus:ring-offset-black' | ||
/> | ||
</div> | ||
</div> | ||
); | ||
} |
Oops, something went wrong.