diff --git a/web/components/contract/contract-info-dialog.tsx b/web/components/contract/contract-info-dialog.tsx
index b5ecea15..0393d10f 100644
--- a/web/components/contract/contract-info-dialog.tsx
+++ b/web/components/contract/contract-info-dialog.tsx
@@ -20,7 +20,7 @@ import { TagsInput } from 'web/components/tags-input'
import { DuplicateContractButton } from '../copy-contract-button'
export const contractDetailsButtonClassName =
- 'group flex items-center rounded-md px-3 py-2 text-sm font-medium cursor-pointer hover:bg-gray-100 text-gray-400 hover:text-gray-500'
+ 'group flex items-center rounded-md px-3 py-2 text-sm font-medium cursor-pointer hover:bg-gray-100 text-gray-400 hover:text-gray-500'
export function ContractInfoDialog(props: { contract: Contract; bets: Bet[] }) {
const { contract, bets } = props
diff --git a/web/components/manalink-card.tsx b/web/components/manalink-card.tsx
index b5a79091..bd72e75e 100644
--- a/web/components/manalink-card.tsx
+++ b/web/components/manalink-card.tsx
@@ -5,6 +5,12 @@ import { Col } from 'web/components/layout/col'
import { Row } from 'web/components/layout/row'
import { User } from 'web/lib/firebase/users'
import { Button } from './button'
+import { Claim, Manalink } from 'common/manalink'
+import { useState } from 'react'
+import { ShareIconButton } from './share-icon-button'
+import { DotsHorizontalIcon, XCircleIcon } from '@heroicons/react/solid'
+import { contractDetailsButtonClassName } from './contract/contract-info-dialog'
+import { useUserById } from 'web/hooks/use-user'
export type ManalinkInfo = {
expiresTime: number | null
@@ -15,19 +21,21 @@ export type ManalinkInfo = {
}
export function ManalinkCard(props: {
- user: User | null | undefined
+ user?: User | null | undefined
className?: string
info: ManalinkInfo
- isClaiming: boolean
+ isClaiming?: boolean
onClaim?: () => void
+ preview?: boolean
}) {
- const { user, className, isClaiming, info, onClaim } = props
+ const { user, className, isClaiming, info, onClaim, preview = false } = props
const { expiresTime, maxUses, uses, amount, message } = info
return (
@@ -44,12 +52,18 @@ export function ManalinkCard(props: {

-
+
{formatMoney(amount)}
@@ -57,52 +71,151 @@ export function ManalinkCard(props: {
{message}
-
-
-
+ {!preview && (
+
+
+
+ )}
)
}
-export function ManalinkCardPreview(props: {
+export function ManalinkCardFromView(props: {
className?: string
- info: ManalinkInfo
+ link: Manalink
+ highlightedSlug: string
}) {
- const { className, info } = props
- const { expiresTime, maxUses, uses, amount, message } = info
+ const { className, link, highlightedSlug } = props
+ const { message, amount, expiresTime, maxUses, claims } = link
+
+ const [details, setDetails] = useState(false)
+
return (
-
-
-
- {maxUses != null
- ? `${maxUses - uses}/${maxUses} uses left`
- : `Unlimited use`}
+ <>
+
+
+ {details && (
+
+ )}
+
+
+ {maxUses != null
+ ? `${maxUses - claims.length}/${maxUses} uses left`
+ : `Unlimited use`}
+
+
+ {expiresTime != null
+ ? `Expires ${fromNow(expiresTime)}`
+ : 'Never expires'}
+
+
+
-
- {expiresTime != null
- ? `Expires ${fromNow(expiresTime)}`
- : 'Never expires'}
+
+
+
+ {formatMoney(amount)}
+
+
+
+
+
{message || '\n\n'}
+
+
+ >
+ )
+}
+
+function ClaimsList(props: { link: Manalink; className: string }) {
+ const { link, className } = props
+ return (
+ <>
+
+
+ Claimed by...
+
+
+ {link.claims.length > 0 ? (
+ <>
+ {link.claims.map((claim) => (
+
+
+
+ ))}
+ >
+ ) : (
+
+ No one has claimed this manalink yet! Share your manalink to start
+ spreading the wealth.
+
+ )}
-
-

-
-
- {formatMoney(amount)}
- {message}
-
-
-
+ >
)
}
+
+function Claim(props: { claim: Claim }) {
+ const { claim } = props
+ const who = useUserById(claim.toId)
+ return (
+
+ {who?.name || 'Loading...'}
+ {fromNow(claim.claimedTime)}
+
+ )
+}
+
+function getManalinkGradient(amount: number) {
+ if (amount < 20) {
+ return 'from-slate-300 via-slate-500 to-slate-800'
+ } else if (amount >= 20 && amount < 50) {
+ return 'from-indigo-300 via-indigo-500 to-indigo-800'
+ } else if (amount >= 50 && amount < 100) {
+ return 'from-violet-300 via-violet-500 to-violet-800'
+ } else if (amount >= 100) {
+ return 'from-indigo-300 via-violet-500 to-rose-400'
+ }
+}
diff --git a/web/components/manalinks/create-links-button.tsx b/web/components/manalinks/create-links-button.tsx
index 0d1d603e..21e137c3 100644
--- a/web/components/manalinks/create-links-button.tsx
+++ b/web/components/manalinks/create-links-button.tsx
@@ -4,7 +4,11 @@ import { Col } from '../layout/col'
import { Row } from '../layout/row'
import { Title } from '../title'
import { User } from 'common/user'
-import { ManalinkCardPreview, ManalinkInfo } from 'web/components/manalink-card'
+import {
+ ManalinkCard,
+ ManalinkCardPreview,
+ ManalinkInfo,
+} from 'web/components/manalink-card'
import { createManalink } from 'web/lib/firebase/manalinks'
import { Modal } from 'web/components/layout/modal'
import Textarea from 'react-expanding-textarea'
@@ -191,7 +195,7 @@ function CreateManalinkForm(props: {
{finishedCreating && (
<>
-
+
void
scrollToTop?: boolean
+ className?: string
}) {
- const { page, itemsPerPage, totalItems, setPage, scrollToTop } = props
+ const { page, itemsPerPage, totalItems, setPage, scrollToTop, className } =
+ props
const maxPage = Math.ceil(totalItems / itemsPerPage) - 1
return (