handle all singular units appropriately

This commit is contained in:
keyan 2023-08-08 16:31:43 -05:00
parent 9941bc6519
commit 3cfeede46a
6 changed files with 43 additions and 12 deletions

View File

@ -2,6 +2,7 @@ import Badge from 'react-bootstrap/Badge'
import OverlayTrigger from 'react-bootstrap/OverlayTrigger'
import Tooltip from 'react-bootstrap/Tooltip'
import CowboyHatIcon from '../svgs/cowboy.svg'
import { numWithUnits } from '../lib/format'
export default function CowboyHat ({ user, badge, className = 'ms-1', height = 16, width = 16 }) {
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
return (
<HatTooltip overlayText={streak ? `${streak} days` : 'new'}>
<HatTooltip overlayText={streak
? `${numWithUnits(streak, { abbreviate: false, unitSingular: 'day', unitPlural: 'days' })}`
: 'new'}
>
{badge
? (
<Badge bg='grey-medium' className='ms-2 d-inline-flex align-items-center'>

View File

@ -17,7 +17,10 @@ import BookmarkDropdownItem from './bookmark'
import SubscribeDropdownItem from './subscribe'
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 me = useMe()
const router = useRouter()
@ -34,7 +37,11 @@ export default function ItemInfo ({ item, pendingSats, full, commentsText, comme
<div className={className || `${styles.other}`}>
{!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 + 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'
>
{item.ncomments} {item.ncomments === 1 ? commentTextSingular || 'comment' : commentsText || 'comments'}
{numWithUnits(item.ncomments, {
abbreviate: false,
unitPlural: commentsText,
unitSingular: commentTextSingular
})}
{hasNewComments &&
<span className={styles.notification}>
<span className='invisible'>{' '}</span>

View File

@ -133,7 +133,11 @@ function Streak ({ n }) {
]
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]
@ -177,7 +181,12 @@ function Invitification ({ n }) {
return (
<>
<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>
<div className='ms-4 me-2 mt-1'>
<Invite
@ -198,7 +207,7 @@ function NostrZap ({ n }) {
return (
<>
<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'>
{npub.slice(0, 10)}...
</Link>

View File

@ -1,6 +1,6 @@
import { gql, useMutation } from '@apollo/client'
import Button from 'react-bootstrap/Button'
import { fixedDecimal } from '../lib/format'
import { fixedDecimal, numWithUnits } from '../lib/format'
import { timeLeft } from '../lib/time'
import { useMe } from './me'
import styles from './poll.module.css'
@ -86,7 +86,7 @@ export default function Poll ({ item }) {
key={v.id} v={v}
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>
)
}

View File

@ -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'}`
}
if (item.ncomments) {
desc += ` [${item.ncomments} comments`
desc += ` [${numWithUnits(item.ncomments, { unitSingular: 'comment', unitPlural: 'comments' })}`
if (item.boost) {
desc += `, ${item.boost} boost`
}
@ -69,7 +69,7 @@ export default function Seo ({ sub, item, 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 (

View File

@ -17,6 +17,7 @@ import Avatar from './avatar'
import CowboyHat from './cowboy-hat'
import { userSchema } from '../lib/validate'
import { useShowModal } from './modal'
import { numWithUnits } from '../lib/format'
export default function UserHeader ({ user }) {
const router = useRouter()
@ -35,7 +36,13 @@ export default function UserHeader ({ user }) {
</Nav.Item>
<Nav.Item>
<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>
</Nav.Item>
</Nav>