Inga/manalink bug fixes (#653)

* fixed manalinks bug of claiming own manalink, and also rerouting to home upon claiming if not logged in
* no more multiple hardcoded manalink messages
This commit is contained in:
ingawei 2022-07-15 18:42:37 -07:00 committed by GitHub
parent eed7990c3c
commit 7d24a3e4a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 34 additions and 25 deletions

View File

@ -27,6 +27,7 @@ Adapted from https://firebase.google.com/docs/functions/get-started
1. `$ brew install java`
2. `$ sudo ln -sfn /opt/homebrew/opt/openjdk/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdk`
2. `$ gcloud auth login` to authenticate the CLI tools to Google Cloud
3. `$ gcloud config set project <project-id>` to choose the project (`$ gcloud projects list` to see options)
4. `$ mkdir firestore_export` to create a folder to store the exported database
@ -53,7 +54,10 @@ Adapted from https://firebase.google.com/docs/functions/get-started
## Deploying
0. `$ firebase use prod` to switch to prod
0. After merging, you need to manually deploy to backend:
1. `git checkout main`
1. `git pull origin main`
1. `$ firebase use prod` to switch to prod
1. `$ firebase deploy --only functions` to push your changes live!
(Future TODO: auto-deploy functions on Git push)

View File

@ -28,6 +28,9 @@ export const claimmanalink = newEndpoint({}, async (req, auth) => {
if (amount <= 0 || isNaN(amount) || !isFinite(amount))
throw new APIError(500, 'Invalid amount')
if (auth.uid === fromId)
throw new APIError(400, `You can't claim your own manalink`)
const fromDoc = firestore.doc(`users/${fromId}`)
const fromSnap = await transaction.get(fromDoc)
if (!fromSnap.exists) {

View File

@ -2,12 +2,13 @@ import { ReactNode } from 'react'
import clsx from 'clsx'
export function Button(props: {
children: ReactNode
className?: string
onClick?: () => void
children?: ReactNode
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
color?: 'green' | 'red' | 'blue' | 'indigo' | 'yellow' | 'gray'
type?: 'button' | 'reset' | 'submit'
disabled?: boolean
}) {
const {
children,
@ -16,6 +17,7 @@ export function Button(props: {
size = 'md',
color = 'indigo',
type = 'button',
disabled = false,
} = props
const sizeClasses = {
@ -30,7 +32,7 @@ export function Button(props: {
<button
type={type}
className={clsx(
'font-md items-center justify-center rounded-md border border-transparent shadow-sm hover:transition-colors',
'font-md items-center justify-center rounded-md border border-transparent shadow-sm hover:transition-colors disabled:cursor-not-allowed disabled:opacity-50',
sizeClasses,
color === 'green' && 'btn-primary text-white',
color === 'red' && 'bg-red-400 text-white hover:bg-red-500',
@ -40,6 +42,7 @@ export function Button(props: {
color === 'gray' && 'bg-gray-200 text-gray-700 hover:bg-gray-300',
className
)}
disabled={disabled}
onClick={onClick}
>
{children}

View File

@ -3,6 +3,8 @@ import { formatMoney } from 'common/util/format'
import { fromNow } from 'web/lib/util/time'
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'
export type ManalinkInfo = {
expiresTime: number | null
@ -13,13 +15,13 @@ export type ManalinkInfo = {
}
export function ManalinkCard(props: {
user: User | null | undefined
className?: string
info: ManalinkInfo
defaultMessage: string
isClaiming: boolean
onClaim?: () => void
}) {
const { className, defaultMessage, isClaiming, info, onClaim } = props
const { user, className, isClaiming, info, onClaim } = props
const { expiresTime, maxUses, uses, amount, message } = info
return (
<div
@ -52,16 +54,13 @@ export function ManalinkCard(props: {
<div className="mb-1 text-xl text-indigo-500">
{formatMoney(amount)}
</div>
<div>{message || defaultMessage}</div>
<div>{message}</div>
</Col>
<div className="ml-auto">
<button
className={clsx('btn', isClaiming ? 'loading disabled' : '')}
onClick={onClaim}
>
{isClaiming ? '' : 'Claim'}
</button>
<Button onClick={onClaim} disabled={isClaiming}>
{user ? 'Claim' : 'Login'}
</Button>
</div>
</Row>
</div>
@ -71,9 +70,8 @@ export function ManalinkCard(props: {
export function ManalinkCardPreview(props: {
className?: string
info: ManalinkInfo
defaultMessage: string
}) {
const { className, defaultMessage, info } = props
const { className, info } = props
const { expiresTime, maxUses, uses, amount, message } = info
return (
<div
@ -102,7 +100,7 @@ export function ManalinkCardPreview(props: {
<Row className="rounded-b-lg bg-white p-2">
<Col className="text-md">
<div className="mb-1 text-indigo-500">{formatMoney(amount)}</div>
<div className="text-xs">{message || defaultMessage}</div>
<div className="text-xs">{message}</div>
</Col>
</Row>
</div>

View File

@ -66,12 +66,14 @@ function CreateManalinkForm(props: {
const defaultExpire = 'week'
const [expiresIn, setExpiresIn] = useState(defaultExpire)
const defaultMessage = 'from ' + user.name
const [newManalink, setNewManalink] = useState<ManalinkInfo>({
expiresTime: dayjs().add(1, defaultExpire).valueOf(),
amount: 100,
maxUses: 1,
uses: 0,
message: '',
message: defaultMessage,
})
const EXPIRE_OPTIONS = {
@ -161,7 +163,7 @@ function CreateManalinkForm(props: {
<div className="form-control w-full">
<label className="label">Message</label>
<Textarea
placeholder={`From ${user.name}`}
placeholder={defaultMessage}
className="input input-bordered resize-none"
autoFocus
value={newManalink.message}
@ -189,11 +191,7 @@ function CreateManalinkForm(props: {
{finishedCreating && (
<>
<Title className="!my-0" text="Manalink Created!" />
<ManalinkCardPreview
className="my-4"
defaultMessage={`From ${user.name}`}
info={newManalink}
/>
<ManalinkCardPreview className="my-4" info={newManalink} />
<Row
className={clsx(
'rounded border bg-gray-50 py-2 px-3 text-sm text-gray-500 transition-colors duration-700',

View File

@ -6,7 +6,6 @@ import { claimManalink } from 'web/lib/firebase/api'
import { useManalink } from 'web/lib/firebase/manalinks'
import { ManalinkCard } from 'web/components/manalink-card'
import { useUser } from 'web/hooks/use-user'
import { useUserById } from 'web/hooks/use-user'
import { firebaseLogin } from 'web/lib/firebase/users'
export default function ClaimPage() {
@ -17,7 +16,6 @@ export default function ClaimPage() {
const [claiming, setClaiming] = useState(false)
const [error, setError] = useState<string | undefined>(undefined)
const fromUser = useUserById(manalink?.fromId)
if (!manalink) {
return <></>
}
@ -33,7 +31,7 @@ export default function ClaimPage() {
<div className="mx-auto max-w-xl">
<Title text={`Claim M$${manalink.amount} mana`} />
<ManalinkCard
defaultMessage={fromUser?.name || 'Enjoy this mana!'}
user={user}
info={info}
isClaiming={claiming}
onClaim={async () => {
@ -41,6 +39,11 @@ export default function ClaimPage() {
try {
if (user == null) {
await firebaseLogin()
setClaiming(false)
return
}
if (user?.id == manalink.fromId) {
throw new Error("You can't claim your own manalink.")
}
await claimManalink({ slug: manalink.slug })
user && router.push(`/${user.username}?claimed-mana=yes`)