make bio work as paid action

This commit is contained in:
k00b 2024-10-02 18:14:25 -05:00
parent 5fab3abb82
commit 65a7ef10d0
8 changed files with 38 additions and 37 deletions

View File

@ -23,8 +23,8 @@ export async function getCost ({ subName, parentId, uploadIds, boost = 0, bio },
// sub allows freebies (or is a bio or a comment), cost is less than baseCost, not anon, // sub allows freebies (or is a bio or a comment), cost is less than baseCost, not anon,
// cost must be greater than user's balance, and user has not disabled freebies // cost must be greater than user's balance, and user has not disabled freebies
const freebie = bio || (parentId && cost <= baseCost && !!me && const freebie = (parentId || bio) && cost <= baseCost && !!me &&
cost > me?.msats && !me?.disableFreebies) cost > me?.msats && !me?.disableFreebies
return freebie ? BigInt(0) : BigInt(cost) return freebie ? BigInt(0) : BigInt(cost)
} }

View File

@ -19,7 +19,7 @@ export async function getCost ({ id, boost = 0, uploadIds, bio }, { me, models }
throw new Error('creation invoice not paid') throw new Error('creation invoice not paid')
} }
return bio ? BigInt(0) : cost return cost
} }
export async function perform (args, context) { export async function perform (args, context) {

View File

@ -691,22 +691,20 @@ export default {
return Number(photoId) return Number(photoId)
}, },
upsertBio: async (parent, { bio }, { me, models, lnd }) => { upsertBio: async (parent, { text }, { me, models, lnd }) => {
if (!me) { if (!me) {
throw new GqlAuthenticationError() throw new GqlAuthenticationError()
} }
await ssValidate(bioSchema, { bio }) await ssValidate(bioSchema, { text })
const user = await models.user.findUnique({ where: { id: me.id } }) const user = await models.user.findUnique({ where: { id: me.id } })
if (user.bioId) { if (user.bioId) {
await updateItem(parent, { id: user.bioId, text: bio, title: `@${user.name}'s bio` }, { me, models, lnd }) return await updateItem(parent, { id: user.bioId, bio: true, text, title: `@${user.name}'s bio` }, { me, models, lnd })
} else { } else {
await createItem(parent, { bio: true, text: bio, title: `@${user.name}'s bio` }, { me, models, lnd }) return await createItem(parent, { bio: true, text, title: `@${user.name}'s bio` }, { me, models, lnd })
} }
return await models.user.findUnique({ where: { id: me.id } })
}, },
generateApiKey: async (parent, { id }, { models, me }) => { generateApiKey: async (parent, { id }, { models, me }) => {
if (!me) { if (!me) {

View File

@ -33,7 +33,7 @@ export default gql`
setName(name: String!): String setName(name: String!): String
setSettings(settings: SettingsInput!): User setSettings(settings: SettingsInput!): User
setPhoto(photoId: ID!): Int! setPhoto(photoId: ID!): Int!
upsertBio(bio: String!): User! upsertBio(text: String!): ItemPaidAction!
setWalkthrough(tipPopover: Boolean, upvotePopover: Boolean): Boolean setWalkthrough(tipPopover: Boolean, upvotePopover: Boolean): Boolean
unlinkAuth(authType: String!): AuthMethods! unlinkAuth(authType: String!): AuthMethods!
linkUnverifiedEmail(email: String!): Boolean linkUnverifiedEmail(email: String!): Boolean

View File

@ -107,7 +107,7 @@ export default function Item ({
{item.position && (pinnable || !item.subName) {item.position && (pinnable || !item.subName)
? <Pin width={24} height={24} className={styles.pin} /> ? <Pin width={24} height={24} className={styles.pin} />
: item.mine || item.meForward : item.mine || item.meForward
? <Boost item={item} className={styles.upvote} /> ? <Boost item={item} className={classNames(styles.upvote, item.bio && 'invisible')} />
: item.meDontLikeSats > item.meSats : item.meDontLikeSats > item.meSats
? <DownZap width={24} height={24} className={styles.dontLike} item={item} /> ? <DownZap width={24} height={24} className={styles.dontLike} item={item} />
: Number(item.user?.id) === USER_ID.ad : Number(item.user?.id) === USER_ID.ad

View File

@ -205,6 +205,16 @@ export const POLL_VOTE = gql`
} }
}` }`
export const UPSERT_BIO = gql`
${ITEM_PAID_ACTION_FIELDS}
${PAID_ACTION}
mutation upsertBio($text: String!) {
upsertBio(text: $text) {
...ItemPaidActionFields
...PaidActionFields
}
}`
export const CREATE_COMMENT = gql` export const CREATE_COMMENT = gql`
${ITEM_PAID_ACTION_FIELDS} ${ITEM_PAID_ACTION_FIELDS}
${PAID_ACTION} ${PAID_ACTION}

View File

@ -800,7 +800,7 @@ export const phoenixdSchema = object().shape({
}, ['primaryPassword', 'secondaryPassword']) }, ['primaryPassword', 'secondaryPassword'])
export const bioSchema = object({ export const bioSchema = object({
bio: string().required('required').trim() text: string().required('required').trim()
}) })
export const inviteSchema = object({ export const inviteSchema = object({

View File

@ -1,5 +1,5 @@
import Layout from '@/components/layout' import Layout from '@/components/layout'
import { gql, useMutation, useQuery } from '@apollo/client' import { useQuery } from '@apollo/client'
import UserHeader from '@/components/user-header' import UserHeader from '@/components/user-header'
import Button from 'react-bootstrap/Button' import Button from 'react-bootstrap/Button'
import styles from '@/styles/user.module.css' import styles from '@/styles/user.module.css'
@ -8,13 +8,14 @@ import ItemFull from '@/components/item-full'
import { Form, MarkdownInput } from '@/components/form' import { Form, MarkdownInput } from '@/components/form'
import { useMe } from '@/components/me' import { useMe } from '@/components/me'
import { USER_FULL } from '@/fragments/users' import { USER_FULL } from '@/fragments/users'
import { ITEM_FIELDS } from '@/fragments/items'
import { getGetServerSideProps } from '@/api/ssrApollo' import { getGetServerSideProps } from '@/api/ssrApollo'
import { FeeButtonProvider } from '@/components/fee-button' import { FeeButtonProvider } from '@/components/fee-button'
import { bioSchema } from '@/lib/validate' import { bioSchema } from '@/lib/validate'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import PageLoading from '@/components/page-loading' import PageLoading from '@/components/page-loading'
import { ItemButtonBar } from '@/components/post' import { ItemButtonBar } from '@/components/post'
import useItemSubmit from '@/components/use-item-submit'
import { UPSERT_BIO } from '@/fragments/paidAction'
export const getServerSideProps = getGetServerSideProps({ export const getServerSideProps = getGetServerSideProps({
query: USER_FULL, query: USER_FULL,
@ -22,49 +23,41 @@ export const getServerSideProps = getGetServerSideProps({
}) })
export function BioForm ({ handleDone, bio, me }) { export function BioForm ({ handleDone, bio, me }) {
const [upsertBio] = useMutation( const onSubmit = useItemSubmit(UPSERT_BIO, {
gql` navigateOnSubmit: false,
${ITEM_FIELDS} paidMutationOptions: {
mutation upsertBio($bio: String!) { update (cache, { data: { upsertBio: { result, invoice } } }) {
upsertBio(bio: $bio) { if (!result) return
id
bio {
...ItemFields
text
}
}
}`, {
update (cache, { data: { upsertBio } }) {
cache.modify({ cache.modify({
id: `User:${upsertBio.id}`, id: `User:${me.id}`,
fields: { fields: {
bio () { bio () {
return upsertBio.bio return result.text
} }
} }
}) })
} }
},
onSuccessfulSubmit: (data, { resetForm }) => {
handleDone?.()
} }
) })
return ( return (
<div className={styles.createFormContainer}> <div className={styles.createFormContainer}>
<FeeButtonProvider> <FeeButtonProvider>
<Form <Form
initial={{ initial={{
bio: bio?.text || '' text: bio?.text || ''
}} }}
schema={bioSchema} schema={bioSchema}
onSubmit={async values => { onSubmit={onSubmit}
const { error } = await upsertBio({ variables: values })
if (error) throw error
handleDone?.()
}}
storageKeyPrefix={`bio-${me.id}`} storageKeyPrefix={`bio-${me.id}`}
> >
<MarkdownInput <MarkdownInput
topLevel topLevel
name='bio' name='text'
minRows={6} minRows={6}
/> />
<ItemButtonBar createText='save' onCancel={handleDone} /> <ItemButtonBar createText='save' onCancel={handleDone} />