Implement #hashtag grouping of markets

This commit is contained in:
Austin Chen 2021-12-18 04:06:59 -08:00
parent 1851b20f42
commit bc81091243
3 changed files with 73 additions and 4 deletions

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react'
import { Fragment, useState } from 'react'
import {
compute,
Contract,
@ -13,7 +13,7 @@ import router from 'next/router'
import { useUser } from '../hooks/use-user'
import { Row } from './layout/row'
import dayjs from 'dayjs'
import { Title } from './title'
import Link from 'next/link'
function ContractDescription(props: {
contract: Contract
@ -33,9 +33,49 @@ function ContractDescription(props: {
setDescription(editStatement())
}
// Return a JSX span, linkifying @username, #hashtags, and https://...
function Linkify(props: { text: string }) {
const { text } = props
const regex = /(?:^|\s)(?:[@#][a-z0-9_]+|https?:\/\/\S+)/gi
const matches = text.match(regex) || []
const links = matches.map((match) => {
// Matches are in the form: " @username" or "https://example.com"
const whitespace = match.match(/^\s/)
const symbol = match.trim().substring(0, 1)
const tag = match.trim().substring(1)
const href =
{
'@': `/${tag}`,
'#': `/tag/${tag}`,
}[symbol] ?? match
return (
<>
{whitespace}
<Link href={href}>
<a className="text-indigo-700 hover:underline hover:decoration-2">
{symbol}
{tag}
</a>
</Link>
</>
)
})
return (
<span>
{text.split(regex).map((part, i) => (
<Fragment key={i}>
{part}
{links[i]}
</Fragment>
))}
</span>
)
}
return (
<div className="whitespace-pre-line">
{contract.description}
<Linkify text={contract.description} />
<br />
{isCreator &&
!contract.resolution &&

View File

@ -146,7 +146,7 @@ export function SearchableGrid(props: {
return (
<div>
{/* Show a search input next to a sort dropdown */}
<div className="flex justify-between gap-2 my-8">
<div className="flex justify-between gap-2 mt-2 mb-8">
<input
type="text"
value={query}

29
web/pages/tag/[tag].tsx Normal file
View File

@ -0,0 +1,29 @@
import { useRouter } from 'next/router'
import { SearchableGrid } from '../../components/contracts-list'
import { Header } from '../../components/header'
import { Title } from '../../components/title'
import { useContracts } from '../../hooks/use-contracts'
import Markets from '../markets'
export default function TagPage() {
const router = useRouter()
const { tag } = router.query as { tag: string }
let contracts = useContracts()
if (tag && contracts !== 'loading') {
contracts = contracts.filter((contract) =>
contract.description.toLowerCase().includes(`#${tag.toLowerCase()}`)
)
}
return (
<div>
<Header />
<div className="max-w-4xl py-8 mx-auto">
<Title text={`#${tag}`} />
<SearchableGrid contracts={contracts === 'loading' ? [] : contracts} />
</div>
</div>
)
}