84 lines
2.7 KiB
TypeScript
84 lines
2.7 KiB
TypeScript
import { useState } from 'react'
|
|
import { nostrService } from '@/lib/nostr'
|
|
import { t } from '@/lib/i18n'
|
|
import { buildReviewTipZapRequestTags } from '@/lib/zapRequestBuilder'
|
|
import { calculateReviewSplit } from '@/lib/platformCommissions'
|
|
import type { Article, Review } from '@/types/nostr'
|
|
|
|
export interface ReviewTipFormController {
|
|
pubkey: string | null
|
|
text: string
|
|
loading: boolean
|
|
error: string | null
|
|
split: ReturnType<typeof calculateReviewSplit>
|
|
setText: (value: string) => void
|
|
handleSubmit: (e: React.FormEvent) => Promise<void>
|
|
}
|
|
|
|
export function useReviewTipFormController(params: {
|
|
review: Review
|
|
article: Article
|
|
pubkey: string | null
|
|
onSuccess?: () => void
|
|
}): ReviewTipFormController {
|
|
const [text, setText] = useState('')
|
|
const [loading, setLoading] = useState(false)
|
|
const [error, setError] = useState<string | null>(null)
|
|
const split = calculateReviewSplit()
|
|
|
|
const handleSubmit = async (e: React.FormEvent): Promise<void> => {
|
|
e.preventDefault()
|
|
if (!params.pubkey) {
|
|
return
|
|
}
|
|
|
|
setLoading(true)
|
|
setError(null)
|
|
try {
|
|
await createAndPublishZapRequest({ review: params.review, article: params.article, text, split })
|
|
setText('')
|
|
params.onSuccess?.()
|
|
} catch (submitError) {
|
|
setError(submitError instanceof Error ? submitError.message : t('reviewTip.form.error.paymentFailed'))
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
return { pubkey: params.pubkey, text, loading, error, split, setText, handleSubmit }
|
|
}
|
|
|
|
async function createAndPublishZapRequest(params: {
|
|
review: Review
|
|
article: Article
|
|
text: string
|
|
split: ReturnType<typeof calculateReviewSplit>
|
|
}): Promise<void> {
|
|
if (!nostrService.getPrivateKey()) {
|
|
throw new Error(t('reviewTip.form.error.noPrivateKey'))
|
|
}
|
|
|
|
const category = getArticleCategoryForTip(params.article)
|
|
const zapRequestTags = buildReviewTipZapRequestTags({
|
|
articleId: params.article.id,
|
|
reviewId: params.review.id,
|
|
authorPubkey: params.article.pubkey,
|
|
reviewerPubkey: params.review.reviewerPubkey,
|
|
...(category ? { category } : {}),
|
|
...(params.article.seriesId ? { seriesId: params.article.seriesId } : {}),
|
|
...(params.text.trim() ? { text: params.text.trim() } : {}),
|
|
})
|
|
|
|
await nostrService.createZapRequest(params.review.reviewerPubkey, params.review.id, params.split.total, zapRequestTags)
|
|
}
|
|
|
|
function getArticleCategoryForTip(article: Article): 'science-fiction' | 'scientific-research' | undefined {
|
|
if (article.category === 'author-presentation') {
|
|
return undefined
|
|
}
|
|
if (article.category === 'science-fiction' || article.category === 'scientific-research') {
|
|
return article.category
|
|
}
|
|
return undefined
|
|
}
|