Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
134 lines
4.2 KiB
TypeScript
134 lines
4.2 KiB
TypeScript
'use client'
|
||
|
||
import type { AdminEventDetailData } from './types'
|
||
|
||
import { useEffect, useState } from 'react'
|
||
|
||
import Button from '@/components/formElements/Button'
|
||
import Input from '@/components/formElements/Input'
|
||
import Modal from '@/components/modals/Modal'
|
||
import { coerceToString } from '@/helpers'
|
||
import { updateEventCommissionAsAdmin } from '@/services/events'
|
||
import useAdminAction from '@/hooks/useAdminAction'
|
||
|
||
interface AdminEventCommissionModalProps {
|
||
eventId: string
|
||
commissionPercent: number | null | undefined
|
||
isOpen: boolean
|
||
onOpenChange: (open: boolean) => void
|
||
onUpdated: (updated: AdminEventDetailData) => void
|
||
}
|
||
|
||
const AdminEventCommissionModal = ({ eventId, commissionPercent, isOpen, onOpenChange, onUpdated }: AdminEventCommissionModalProps) => {
|
||
const [commissionInput, setCommissionInput] = useState('')
|
||
const [commissionError, setCommissionError] = useState<string | null>(null)
|
||
const { pendingId, runAction } = useAdminAction()
|
||
|
||
useEffect(() => {
|
||
if (!isOpen) return
|
||
setCommissionInput(commissionPercent != null ? String(commissionPercent) : '')
|
||
setCommissionError(null)
|
||
}, [isOpen, commissionPercent])
|
||
|
||
const handleSaveCommission = () => {
|
||
const trimmed = commissionInput.trim()
|
||
const parsed = Number(trimmed)
|
||
|
||
if (trimmed === '' || Number.isNaN(parsed) || parsed < 0 || parsed > 100) {
|
||
setCommissionError('درصد کمیسیون باید عددی بین ۰ تا ۱۰۰ باشد')
|
||
|
||
return
|
||
}
|
||
|
||
void runAction(
|
||
'commission',
|
||
async () => {
|
||
const updated = (await updateEventCommissionAsAdmin(eventId, parsed)) as AdminEventDetailData
|
||
|
||
onUpdated(updated)
|
||
onOpenChange(false)
|
||
},
|
||
'کمیسیون رویداد بهروزرسانی شد'
|
||
)
|
||
}
|
||
|
||
const handleResetCommission = () =>
|
||
runAction(
|
||
'commission',
|
||
async () => {
|
||
const updated = (await updateEventCommissionAsAdmin(eventId, null)) as AdminEventDetailData
|
||
|
||
onUpdated(updated)
|
||
onOpenChange(false)
|
||
},
|
||
'کمیسیون رویداد به پیشفرض پلتفرم بازگشت'
|
||
)
|
||
|
||
return (
|
||
<Modal
|
||
footerChildren={
|
||
<div className="flex w-full items-center justify-between gap-2">
|
||
{commissionPercent != null ? (
|
||
<Button
|
||
color="warning"
|
||
disabled={pendingId === 'commission'}
|
||
isLoading={pendingId === 'commission'}
|
||
size="sm"
|
||
variant="flat"
|
||
onClick={() => void handleResetCommission()}
|
||
>
|
||
بازگشت به پیشفرض پلتفرم
|
||
</Button>
|
||
) : (
|
||
<span />
|
||
)}
|
||
<div className="flex items-center gap-2">
|
||
<Button
|
||
disabled={pendingId === 'commission'}
|
||
size="sm"
|
||
variant="flat"
|
||
onClick={() => {
|
||
onOpenChange(false)
|
||
}}
|
||
>
|
||
انصراف
|
||
</Button>
|
||
<Button
|
||
disabled={pendingId === 'commission'}
|
||
isLoading={pendingId === 'commission'}
|
||
size="sm"
|
||
onClick={handleSaveCommission}
|
||
>
|
||
ذخیره
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
}
|
||
isOpen={isOpen}
|
||
title="ویرایش کمیسیون پلتفرم"
|
||
onOpenChange={onOpenChange}
|
||
>
|
||
<div className="flex flex-col gap-4">
|
||
<p className="text-sm text-text-muted">
|
||
درصد کمیسیونی که پلتفرم از این رویداد کسر میکند. با خالی گذاشتن این مقدار (بازگشت به پیشفرض)، رویداد از پیشفرض پلتفرم پیروی
|
||
میکند.
|
||
</p>
|
||
<Input
|
||
generalType="input"
|
||
inputType="number"
|
||
label="درصد کمیسیون (۰ تا ۱۰۰)"
|
||
name="commissionPercent"
|
||
value={commissionInput}
|
||
onValueChange={(value) => {
|
||
setCommissionInput(coerceToString(value))
|
||
setCommissionError(null)
|
||
}}
|
||
/>
|
||
{commissionError && <span className="text-tiny text-fourth-900">{commissionError}</span>}
|
||
</div>
|
||
</Modal>
|
||
)
|
||
}
|
||
|
||
export default AdminEventCommissionModal
|