Add SMS templates UI, prepaid balance settings, and list filter layout.
Business settings manage templates and balance; Super Admin verifies templates and tops up via SMS settings; filters use a separate panel with even field gaps. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
8f0b4cef85
commit
0eb19bbebd
@@ -193,22 +193,34 @@ export interface SendCustomersBulkSmsResult {
|
||||
source?: string
|
||||
}
|
||||
|
||||
export async function sendCustomerSms(userId: string, message: string) {
|
||||
export async function sendCustomerSms(
|
||||
userId: string,
|
||||
message: string,
|
||||
templateId?: string | null,
|
||||
) {
|
||||
return apiRequest<SendCustomerSmsResult>(businessPath(`/${userId}/sms`), {
|
||||
method: 'POST',
|
||||
auth: true,
|
||||
body: { message },
|
||||
body: {
|
||||
message,
|
||||
...(templateId ? { templateId } : {}),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/** Bulk SMS via Gama SendBulk. Omit userIds (or pass []) to send to all enabled customers. */
|
||||
export async function sendCustomersBulkSms(message: string, userIds?: string[]) {
|
||||
export async function sendCustomersBulkSms(
|
||||
message: string,
|
||||
userIds?: string[],
|
||||
templateId?: string | null,
|
||||
) {
|
||||
return apiRequest<SendCustomersBulkSmsResult>(businessPath('/sms'), {
|
||||
method: 'POST',
|
||||
auth: true,
|
||||
body: {
|
||||
message,
|
||||
...(userIds && userIds.length > 0 ? { userIds } : {}),
|
||||
...(templateId ? { templateId } : {}),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -107,12 +107,17 @@ export interface WebsiteSettings {
|
||||
sitemapConfig?: WebsiteSitemapConfig | null
|
||||
}
|
||||
|
||||
export interface SmsSettings {
|
||||
senderNumber: string | null
|
||||
}
|
||||
|
||||
export interface BusinessSettings {
|
||||
branding: BrandingSettings
|
||||
dashboard: DashboardSettings
|
||||
store: StoreSettings
|
||||
modules?: ModulesSettings
|
||||
website?: WebsiteSettings
|
||||
sms?: SmsSettings
|
||||
}
|
||||
|
||||
export interface SettingsResponse {
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import { apiRequest } from '../lib/api'
|
||||
import { getActiveBusinessId } from '../lib/businessContext'
|
||||
|
||||
export type SmsTemplateVerificationStatus = 'free' | 'pending' | 'verified'
|
||||
|
||||
export interface SmsTemplate {
|
||||
id: string
|
||||
businessId: string
|
||||
name: string
|
||||
body: string
|
||||
verificationStatus: SmsTemplateVerificationStatus
|
||||
isVerified: boolean
|
||||
verifiedAt: string | null
|
||||
verifiedBy: string | null
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
function smsPath(suffix = '') {
|
||||
const businessId = getActiveBusinessId()
|
||||
if (!businessId) {
|
||||
throw new Error('No active business selected. Please sign in again.')
|
||||
}
|
||||
return `/businesses/${businessId}/sms${suffix}`
|
||||
}
|
||||
|
||||
export async function listSmsTemplates(signal?: AbortSignal) {
|
||||
return apiRequest<{ items: SmsTemplate[]; variables: string[] }>(
|
||||
smsPath('/templates'),
|
||||
{ auth: true, signal },
|
||||
)
|
||||
}
|
||||
|
||||
export async function createSmsTemplate(payload: { name: string; body: string }) {
|
||||
return apiRequest<{ template: SmsTemplate }>(smsPath('/templates'), {
|
||||
method: 'POST',
|
||||
auth: true,
|
||||
body: payload,
|
||||
})
|
||||
}
|
||||
|
||||
export async function updateSmsTemplate(
|
||||
templateId: string,
|
||||
payload: { name?: string; body?: string },
|
||||
) {
|
||||
return apiRequest<{ template: SmsTemplate }>(smsPath(`/templates/${templateId}`), {
|
||||
method: 'PATCH',
|
||||
auth: true,
|
||||
body: payload,
|
||||
})
|
||||
}
|
||||
|
||||
export async function requestSmsTemplateVerification(templateId: string) {
|
||||
return apiRequest<{ template: SmsTemplate }>(
|
||||
smsPath(`/templates/${templateId}/request-verification`),
|
||||
{ method: 'POST', auth: true },
|
||||
)
|
||||
}
|
||||
|
||||
export async function deleteSmsTemplate(templateId: string) {
|
||||
return apiRequest<{ success: boolean }>(smsPath(`/templates/${templateId}`), {
|
||||
method: 'DELETE',
|
||||
auth: true,
|
||||
})
|
||||
}
|
||||
|
||||
export async function getSmsCredit(signal?: AbortSignal) {
|
||||
return apiRequest<{
|
||||
balance: number
|
||||
/** @deprecated use balance */
|
||||
credit: number | null
|
||||
currency: string | null
|
||||
message: string | null
|
||||
}>(smsPath('/credit'), { auth: true, signal })
|
||||
}
|
||||
Reference in New Issue
Block a user