Show SMS sent breakdown by type in admin and business settings.

Data rows for total/mass/singular/auth/auto/admin; balance stays a credit data row.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-09-09 11:31:18 +03:30
co-authored by Cursor
parent 6bc57f26ed
commit dbc17b2589
8 changed files with 194 additions and 16 deletions
@@ -43,6 +43,14 @@ export function SmsSettingsSection() {
const isFa = locale === 'fa'
const { showToast } = useToast()
const [balance, setBalance] = useState(0)
const [sentCount, setSentCount] = useState(0)
const [sentByType, setSentByType] = useState({
mass: 0,
singular: 0,
auth: 0,
autoCustomer: 0,
admin: 0,
})
const [templates, setTemplates] = useState<SmsTemplate[]>([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState('')
@@ -73,6 +81,14 @@ export function SmsSettingsSection() {
if (signal?.aborted) return
setTemplates(tpl.items)
setBalance(creditRes.balance ?? creditRes.credit ?? 0)
setSentCount(creditRes.sentCount ?? 0)
setSentByType({
mass: creditRes.sentByType?.mass ?? 0,
singular: creditRes.sentByType?.singular ?? 0,
auth: creditRes.sentByType?.auth ?? 0,
autoCustomer: creditRes.sentByType?.autoCustomer ?? 0,
admin: creditRes.sentByType?.admin ?? 0,
})
} catch (err) {
if (isAbortError(err)) return
setError(err instanceof ApiError ? err.message : t('settings.sms.errorLoad'))
@@ -272,6 +288,26 @@ export function SmsSettingsSection() {
</strong>
</div>
<div className={settingsStyles.smsSentStack} role="group" aria-label={t('settings.sms.sentCount')}>
{(
[
['settings.sms.sentTotal', sentCount],
['settings.sms.sentMass', sentByType.mass],
['settings.sms.sentSingular', sentByType.singular],
['settings.sms.sentAuth', sentByType.auth],
['settings.sms.sentAutoCustomer', sentByType.autoCustomer],
['settings.sms.sentAdmin', sentByType.admin],
] as const
).map(([labelKey, value]) => (
<div key={labelKey} className={`${settingsStyles.smsCreditRow} ${settingsStyles.smsSentRow}`}>
<span className={settingsStyles.smsCreditLabel}>{t(labelKey)}</span>
<strong className={settingsStyles.smsCreditValue}>
{loading ? '…' : value.toLocaleString(isFa ? 'fa-IR' : 'en-US')}
</strong>
</div>
))}
</div>
<div className={settingsStyles.smsTemplatesSummary}>
<div className={settingsStyles.smsTemplatesSummaryText}>
<h4 className={settingsStyles.smsTemplatesTitle}>{t('settings.sms.templates')}</h4>
+12
View File
@@ -1699,6 +1699,12 @@ const en = {
'settings.sms.balanceHint':
'Balance is SMS credits. Each 64 characters costs 1 credit per recipient (login, orders, customer SMS, etc.). Contact Meshkee to top up.',
'settings.sms.sentCount': 'SMS sent',
'settings.sms.sentTotal': 'SMS sent (total)',
'settings.sms.sentMass': 'Mass send',
'settings.sms.sentSingular': 'Singular',
'settings.sms.sentAuth': 'Auth service',
'settings.sms.sentAutoCustomer': 'Auto customer',
'settings.sms.sentAdmin': 'Admin notification',
'settings.sms.credit': 'Account credit',
'settings.sms.creditUnavailable': 'Unavailable',
'settings.sms.templates': 'Templates',
@@ -4163,6 +4169,12 @@ const fa: Record<MessageKey, string> = {
'settings.sms.balanceHint':
'اعتبار به واحد پیامک است. هر ۶۴ کاراکتر برای هر گیرنده ۱ اعتبار مصرف می‌کند (ورود، سفارش، پیامک مشتری و غیره). برای افزایش با مشکی تماس بگیرید.',
'settings.sms.sentCount': 'پیامک ارسال‌شده',
'settings.sms.sentTotal': 'پیامک ارسال‌شده (کل)',
'settings.sms.sentMass': 'ارسال گروهی',
'settings.sms.sentSingular': 'ارسال تکی',
'settings.sms.sentAuth': 'سرویس احراز هویت',
'settings.sms.sentAutoCustomer': 'خودکار مشتری',
'settings.sms.sentAdmin': 'اعلان مدیر',
'settings.sms.credit': 'اعتبار حساب',
'settings.sms.creditUnavailable': 'در دسترس نیست',
'settings.sms.templates': 'قالب‌ها',
@@ -249,6 +249,29 @@
font-family: var(--font-ui);
}
.smsSentStack {
display: flex;
flex-direction: column;
gap: 8px;
margin-top: 10px;
}
.smsSentRow {
margin-top: 0;
background: rgba(15, 23, 42, 0.04);
border-color: rgba(15, 23, 42, 0.1);
}
.smsSentRow .smsCreditLabel,
.smsSentRow .smsCreditValue {
color: var(--text-primary);
font-size: 13px;
}
.smsSentRow .smsCreditValue {
font-size: 14px;
}
.smsTemplatesSummary {
display: flex;
align-items: center;
@@ -71,6 +71,13 @@ export async function getSmsCredit(signal?: AbortSignal) {
credit: number | null
/** Lifetime SMS messages billed (one per recipient). */
sentCount: number
sentByType: {
mass: number
singular: number
auth: number
autoCustomer: number
admin: number
}
unit: 'credits'
currency: string | null
message: string | null