feat: add regex validation for funnel steps and improve error handling in CreateFunnelPage
This commit is contained in:
@@ -6,6 +6,15 @@ import { createFunnel, type CreateFunnelRequest, type FunnelStep } from '@/lib/a
|
|||||||
import { toast, Input, Button, ChevronLeftIcon, PlusIcon, TrashIcon } from '@ciphera-net/ui'
|
import { toast, Input, Button, ChevronLeftIcon, PlusIcon, TrashIcon } from '@ciphera-net/ui'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
|
||||||
|
function isValidRegex(pattern: string): boolean {
|
||||||
|
try {
|
||||||
|
new RegExp(pattern)
|
||||||
|
return true
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default function CreateFunnelPage() {
|
export default function CreateFunnelPage() {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -13,6 +22,7 @@ export default function CreateFunnelPage() {
|
|||||||
|
|
||||||
const [name, setName] = useState('')
|
const [name, setName] = useState('')
|
||||||
const [description, setDescription] = useState('')
|
const [description, setDescription] = useState('')
|
||||||
|
// * Backend requires at least one step (API binding min=1, DB rejects empty steps)
|
||||||
const [steps, setSteps] = useState<Omit<FunnelStep, 'order'>[]>([
|
const [steps, setSteps] = useState<Omit<FunnelStep, 'order'>[]>([
|
||||||
{ name: 'Step 1', value: '/', type: 'exact' },
|
{ name: 'Step 1', value: '/', type: 'exact' },
|
||||||
{ name: 'Step 2', value: '', type: 'exact' }
|
{ name: 'Step 2', value: '', type: 'exact' }
|
||||||
@@ -47,6 +57,10 @@ export default function CreateFunnelPage() {
|
|||||||
toast.error('Please enter a path for all steps')
|
toast.error('Please enter a path for all steps')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (steps.some(s => s.type === 'regex' && !isValidRegex(s.value))) {
|
||||||
|
toast.error('Invalid regex in one or more steps. Check the pattern for steps with type "regex".')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setSaving(true)
|
setSaving(true)
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export async function deleteFunnel(siteId: string, funnelId: string): Promise<vo
|
|||||||
|
|
||||||
const DATE_ONLY_REGEX = /^\d{4}-\d{2}-\d{2}$/
|
const DATE_ONLY_REGEX = /^\d{4}-\d{2}-\d{2}$/
|
||||||
|
|
||||||
/** Normalize date-only (YYYY-MM-DD) to RFC3339 for backend funnel stats API. */
|
/** Normalize date-only (YYYY-MM-DD) to RFC3339 for backend funnel stats API. Uses UTC for boundaries (API/server timestamps are UTC). */
|
||||||
function toRFC3339Range(from: string, to: string): { from: string; to: string } {
|
function toRFC3339Range(from: string, to: string): { from: string; to: string } {
|
||||||
return {
|
return {
|
||||||
from: DATE_ONLY_REGEX.test(from) ? `${from}T00:00:00.000Z` : from,
|
from: DATE_ONLY_REGEX.test(from) ? `${from}T00:00:00.000Z` : from,
|
||||||
|
|||||||
Reference in New Issue
Block a user