handle all singular units appropriately
This commit is contained in:
parent
9941bc6519
commit
3cfeede46a
|
@ -2,6 +2,7 @@ import Badge from 'react-bootstrap/Badge'
|
||||||
import OverlayTrigger from 'react-bootstrap/OverlayTrigger'
|
import OverlayTrigger from 'react-bootstrap/OverlayTrigger'
|
||||||
import Tooltip from 'react-bootstrap/Tooltip'
|
import Tooltip from 'react-bootstrap/Tooltip'
|
||||||
import CowboyHatIcon from '../svgs/cowboy.svg'
|
import CowboyHatIcon from '../svgs/cowboy.svg'
|
||||||
|
import { numWithUnits } from '../lib/format'
|
||||||
|
|
||||||
export default function CowboyHat ({ user, badge, className = 'ms-1', height = 16, width = 16 }) {
|
export default function CowboyHat ({ user, badge, className = 'ms-1', height = 16, width = 16 }) {
|
||||||
if (user?.streak === null || user.hideCowboyHat) {
|
if (user?.streak === null || user.hideCowboyHat) {
|
||||||
|
@ -10,7 +11,10 @@ export default function CowboyHat ({ user, badge, className = 'ms-1', height = 1
|
||||||
|
|
||||||
const streak = user.streak
|
const streak = user.streak
|
||||||
return (
|
return (
|
||||||
<HatTooltip overlayText={streak ? `${streak} days` : 'new'}>
|
<HatTooltip overlayText={streak
|
||||||
|
? `${numWithUnits(streak, { abbreviate: false, unitSingular: 'day', unitPlural: 'days' })}`
|
||||||
|
: 'new'}
|
||||||
|
>
|
||||||
{badge
|
{badge
|
||||||
? (
|
? (
|
||||||
<Badge bg='grey-medium' className='ms-2 d-inline-flex align-items-center'>
|
<Badge bg='grey-medium' className='ms-2 d-inline-flex align-items-center'>
|
||||||
|
|
|
@ -17,7 +17,10 @@ import BookmarkDropdownItem from './bookmark'
|
||||||
import SubscribeDropdownItem from './subscribe'
|
import SubscribeDropdownItem from './subscribe'
|
||||||
import { CopyLinkDropdownItem } from './share'
|
import { CopyLinkDropdownItem } from './share'
|
||||||
|
|
||||||
export default function ItemInfo ({ item, pendingSats, full, commentsText, commentTextSingular, className, embellishUser, extraInfo, onEdit, editText }) {
|
export default function ItemInfo ({
|
||||||
|
item, pendingSats, full, commentsText = 'comments',
|
||||||
|
commentTextSingular = 'comment', className, embellishUser, extraInfo, onEdit, editText
|
||||||
|
}) {
|
||||||
const editThreshold = new Date(item.createdAt).getTime() + 10 * 60000
|
const editThreshold = new Date(item.createdAt).getTime() + 10 * 60000
|
||||||
const me = useMe()
|
const me = useMe()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
@ -34,7 +37,11 @@ export default function ItemInfo ({ item, pendingSats, full, commentsText, comme
|
||||||
<div className={className || `${styles.other}`}>
|
<div className={className || `${styles.other}`}>
|
||||||
{!item.position &&
|
{!item.position &&
|
||||||
<>
|
<>
|
||||||
<span title={`from ${item.upvotes} stackers ${item.mine
|
<span title={`from ${numWithUnits(item.upvotes, {
|
||||||
|
abbreviate: false,
|
||||||
|
unitSingular: 'stacker',
|
||||||
|
unitPlural: 'stackers'
|
||||||
|
})} ${item.mine
|
||||||
? `\\ ${numWithUnits(item.meSats, { abbreviate: false })} to post`
|
? `\\ ${numWithUnits(item.meSats, { abbreviate: false })} to post`
|
||||||
: `(${numWithUnits(item.meSats + pendingSats, { abbreviate: false })} from me)`} `}
|
: `(${numWithUnits(item.meSats + pendingSats, { abbreviate: false })} from me)`} `}
|
||||||
>
|
>
|
||||||
|
@ -58,7 +65,11 @@ export default function ItemInfo ({ item, pendingSats, full, commentsText, comme
|
||||||
}
|
}
|
||||||
}} title={numWithUnits(item.commentSats)} className='text-reset position-relative'
|
}} title={numWithUnits(item.commentSats)} className='text-reset position-relative'
|
||||||
>
|
>
|
||||||
{item.ncomments} {item.ncomments === 1 ? commentTextSingular || 'comment' : commentsText || 'comments'}
|
{numWithUnits(item.ncomments, {
|
||||||
|
abbreviate: false,
|
||||||
|
unitPlural: commentsText,
|
||||||
|
unitSingular: commentTextSingular
|
||||||
|
})}
|
||||||
{hasNewComments &&
|
{hasNewComments &&
|
||||||
<span className={styles.notification}>
|
<span className={styles.notification}>
|
||||||
<span className='invisible'>{' '}</span>
|
<span className='invisible'>{' '}</span>
|
||||||
|
|
|
@ -133,7 +133,11 @@ function Streak ({ n }) {
|
||||||
]
|
]
|
||||||
|
|
||||||
if (n.days) {
|
if (n.days) {
|
||||||
return `After ${n.days} days, ` + LOST_BLURBS[index]
|
return `After ${numWithUnits(n.days, {
|
||||||
|
abbreviate: false,
|
||||||
|
unitSingular: 'day',
|
||||||
|
unitPlural: 'days'
|
||||||
|
})}, ` + LOST_BLURBS[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
return FOUND_BLURBS[index]
|
return FOUND_BLURBS[index]
|
||||||
|
@ -177,7 +181,12 @@ function Invitification ({ n }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<small className='fw-bold text-secondary ms-2'>
|
<small className='fw-bold text-secondary ms-2'>
|
||||||
your invite has been redeemed by {n.invite.invitees.length} stackers
|
your invite has been redeemed by
|
||||||
|
{numWithUnits(n.invite.invitees.length, {
|
||||||
|
abbreviate: false,
|
||||||
|
unitSingular: 'stacker',
|
||||||
|
unitPlural: 'stackers'
|
||||||
|
})}
|
||||||
</small>
|
</small>
|
||||||
<div className='ms-4 me-2 mt-1'>
|
<div className='ms-4 me-2 mt-1'>
|
||||||
<Invite
|
<Invite
|
||||||
|
@ -198,7 +207,7 @@ function NostrZap ({ n }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className='fw-bold text-nostr ms-2 py-1'>
|
<div className='fw-bold text-nostr ms-2 py-1'>
|
||||||
<NostrIcon width={24} height={24} className='fill-nostr me-1' />{n.earnedSats} sats zap from
|
<NostrIcon width={24} height={24} className='fill-nostr me-1' />{numWithUnits(n.earnedSats)} zap from
|
||||||
<Link className='mx-1 text-reset text-underline' target='_blank' href={`https://snort.social/p/${npub}`} rel='noreferrer'>
|
<Link className='mx-1 text-reset text-underline' target='_blank' href={`https://snort.social/p/${npub}`} rel='noreferrer'>
|
||||||
{npub.slice(0, 10)}...
|
{npub.slice(0, 10)}...
|
||||||
</Link>
|
</Link>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { gql, useMutation } from '@apollo/client'
|
import { gql, useMutation } from '@apollo/client'
|
||||||
import Button from 'react-bootstrap/Button'
|
import Button from 'react-bootstrap/Button'
|
||||||
import { fixedDecimal } from '../lib/format'
|
import { fixedDecimal, numWithUnits } from '../lib/format'
|
||||||
import { timeLeft } from '../lib/time'
|
import { timeLeft } from '../lib/time'
|
||||||
import { useMe } from './me'
|
import { useMe } from './me'
|
||||||
import styles from './poll.module.css'
|
import styles from './poll.module.css'
|
||||||
|
@ -86,7 +86,7 @@ export default function Poll ({ item }) {
|
||||||
key={v.id} v={v}
|
key={v.id} v={v}
|
||||||
progress={item.poll.count ? fixedDecimal(v.count * 100 / item.poll.count, 1) : 0}
|
progress={item.poll.count ? fixedDecimal(v.count * 100 / item.poll.count, 1) : 0}
|
||||||
/>)}
|
/>)}
|
||||||
<div className='text-muted mt-1'>{item.poll.count} votes \ {expiresIn ? `${expiresIn} left` : 'poll ended'}</div>
|
<div className='text-muted mt-1'>{numWithUnits(item.poll.count, { unitSingular: 'vote', unitPlural: 'votes' })} \ {expiresIn ? `${expiresIn} left` : 'poll ended'}</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ export default function Seo ({ sub, item, user }) {
|
||||||
desc = `@${item.user.name} stacked ${numWithUnits(item.sats)} ${item.url ? `posting ${item.url}` : 'with this discussion'}`
|
desc = `@${item.user.name} stacked ${numWithUnits(item.sats)} ${item.url ? `posting ${item.url}` : 'with this discussion'}`
|
||||||
}
|
}
|
||||||
if (item.ncomments) {
|
if (item.ncomments) {
|
||||||
desc += ` [${item.ncomments} comments`
|
desc += ` [${numWithUnits(item.ncomments, { unitSingular: 'comment', unitPlural: 'comments' })}`
|
||||||
if (item.boost) {
|
if (item.boost) {
|
||||||
desc += `, ${item.boost} boost`
|
desc += `, ${item.boost} boost`
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ export default function Seo ({ sub, item, user }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (user) {
|
if (user) {
|
||||||
desc = `@${user.name} has [${user.stacked} stacked, ${user.nposts} posts, ${user.ncomments} comments]`
|
desc = `@${user.name} has [${user.stacked} stacked, ${numWithUnits(user.nitems, { unitSingular: 'item', unitPlural: 'items' })}]`
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -17,6 +17,7 @@ import Avatar from './avatar'
|
||||||
import CowboyHat from './cowboy-hat'
|
import CowboyHat from './cowboy-hat'
|
||||||
import { userSchema } from '../lib/validate'
|
import { userSchema } from '../lib/validate'
|
||||||
import { useShowModal } from './modal'
|
import { useShowModal } from './modal'
|
||||||
|
import { numWithUnits } from '../lib/format'
|
||||||
|
|
||||||
export default function UserHeader ({ user }) {
|
export default function UserHeader ({ user }) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
@ -35,7 +36,13 @@ export default function UserHeader ({ user }) {
|
||||||
</Nav.Item>
|
</Nav.Item>
|
||||||
<Nav.Item>
|
<Nav.Item>
|
||||||
<Link href={'/' + user.name + '/all'} passHref legacyBehavior>
|
<Link href={'/' + user.name + '/all'} passHref legacyBehavior>
|
||||||
<Nav.Link eventKey>{user.nitems} items</Nav.Link>
|
<Nav.Link eventKey>
|
||||||
|
{numWithUnits(user.nitems, {
|
||||||
|
abbreviate: false,
|
||||||
|
unitSingular: 'item',
|
||||||
|
unitPlural: 'items'
|
||||||
|
})}
|
||||||
|
</Nav.Link>
|
||||||
</Link>
|
</Link>
|
||||||
</Nav.Item>
|
</Nav.Item>
|
||||||
</Nav>
|
</Nav>
|
||||||
|
|
Loading…
Reference in New Issue