6cc2d8af58
* Set up Firestore structure for mana bounty links
* Split up manalinks into successes and failures
* Allow clients to create manalinks
* Track txnId and successful users
* Store custom amounts in the link
* List all manalinks you've created
* Support backend for claiming manalinks
* Add some more error handling
* Tweak readme
* Fix typescript breakage
* Revert "Convert common imports in functions to be absolute"
This reverts commit c03518e906
.
* Scaffolding so `claimManalink` works
* Clean up imports
* Barebones endpoint to claim mana
* Fix rules to only allow link creators to query
* Design out claim giftcard
* List all claimed transactions
* Style in a more awesome card
* Fix import
* Padding tweak
* Fix useManalinkTxns hook
* /send -> /link
* Tidy up some details
* Do a bunch of random manalinks work
* Fix up LinksTable to build
* Clean up LinksTable an absurd amount
* Basic details functionality on manalinks table
* Work on manalink claim stuff
* Fix up some merge mess
* Not-signed-in flow implemented
* Better manalinks table
* Only show outstanding links in table
* Use new `ManalinkTxn` type
* /link -> /links
* Change manalinks page UI to use nice looking tabs
* Many fixes to manalinks UI
* Default to 1 use
* Tidying up
* Some copy changes based on feedback
* Add required index
Co-authored-by: Marshall Polaris <marshall@pol.rs>
63 lines
2.0 KiB
TypeScript
63 lines
2.0 KiB
TypeScript
import clsx from 'clsx'
|
|
import Link from 'next/link'
|
|
import { ReactNode, useState } from 'react'
|
|
import { Row } from './row'
|
|
|
|
type Tab = {
|
|
title: string
|
|
tabIcon?: ReactNode
|
|
content: ReactNode
|
|
// If set, change the url to this href when the tab is selected
|
|
href?: string
|
|
}
|
|
|
|
export function Tabs(props: {
|
|
tabs: Tab[]
|
|
defaultIndex?: number
|
|
className?: string
|
|
onClick?: (tabTitle: string, index: number) => void
|
|
}) {
|
|
const { tabs, defaultIndex, className, onClick } = props
|
|
const [activeIndex, setActiveIndex] = useState(defaultIndex ?? 0)
|
|
const activeTab = tabs[activeIndex] as Tab | undefined // can be undefined in weird case
|
|
|
|
return (
|
|
<div>
|
|
<div className="border-b border-gray-200">
|
|
<nav className="-mb-px flex space-x-8" aria-label="Tabs">
|
|
{tabs.map((tab, i) => (
|
|
<Link href={tab.href ?? '#'} key={tab.title} shallow={!!tab.href}>
|
|
<a
|
|
id={`tab-${i}`}
|
|
key={tab.title}
|
|
onClick={(e) => {
|
|
if (!tab.href) {
|
|
e.preventDefault()
|
|
}
|
|
setActiveIndex(i)
|
|
onClick?.(tab.title, i)
|
|
}}
|
|
className={clsx(
|
|
activeIndex === i
|
|
? 'border-indigo-500 text-indigo-600'
|
|
: 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700',
|
|
'cursor-pointer whitespace-nowrap border-b-2 py-3 px-1 text-sm font-medium',
|
|
className
|
|
)}
|
|
aria-current={activeIndex === i ? 'page' : undefined}
|
|
>
|
|
<Row className={'items-center justify-center gap-1'}>
|
|
{tab.tabIcon && <span> {tab.tabIcon}</span>}
|
|
{tab.title}
|
|
</Row>
|
|
</a>
|
|
</Link>
|
|
))}
|
|
</nav>
|
|
</div>
|
|
|
|
<div className="mt-4">{activeTab?.content}</div>
|
|
</div>
|
|
)
|
|
}
|