Fix build errors
This commit is contained in:
@@ -35,7 +35,6 @@ interface EmailEditorProps {
|
|||||||
value: string;
|
value: string;
|
||||||
onChange: (value: string) => void;
|
onChange: (value: string) => void;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
canUploadImages?: boolean;
|
|
||||||
// Optional props for preview header
|
// Optional props for preview header
|
||||||
subject?: string;
|
subject?: string;
|
||||||
from?: string;
|
from?: string;
|
||||||
|
|||||||
@@ -119,6 +119,44 @@ const FilterRow = memo(function FilterRow({filter, onChange, onRemove, available
|
|||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [search, setSearch] = useState('');
|
const [search, setSearch] = useState('');
|
||||||
|
|
||||||
|
// Helper to get default value based on field type
|
||||||
|
const getDefaultValueForType = useCallback((type: string) => {
|
||||||
|
switch (type) {
|
||||||
|
case 'boolean':
|
||||||
|
return true;
|
||||||
|
case 'number':
|
||||||
|
return 0;
|
||||||
|
case 'date':
|
||||||
|
return '';
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Helper to get valid operators for a field type
|
||||||
|
const getOperatorsForType = useCallback((type: string, isEvent: boolean) => {
|
||||||
|
if (isEvent) {
|
||||||
|
return EVENT_OPERATORS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'boolean') {
|
||||||
|
return STANDARD_OPERATORS.filter(op =>
|
||||||
|
['equals', 'notEquals', 'exists', 'notExists'].includes(op.value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'number' || type === 'date') {
|
||||||
|
return STANDARD_OPERATORS.filter(op =>
|
||||||
|
['equals', 'notEquals', 'greaterThan', 'lessThan', 'greaterThanOrEqual', 'lessThanOrEqual', 'exists', 'notExists', 'within'].includes(op.value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// String type - no within operator, no comparison operators
|
||||||
|
return STANDARD_OPERATORS.filter(op =>
|
||||||
|
['equals', 'notEquals', 'contains', 'notContains', 'exists', 'notExists'].includes(op.value)
|
||||||
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const needsValue = !['exists', 'notExists', 'triggered', 'notTriggered'].includes(filter.operator);
|
const needsValue = !['exists', 'notExists', 'triggered', 'notTriggered'].includes(filter.operator);
|
||||||
const needsUnit = ['within', 'triggeredWithin'].includes(filter.operator);
|
const needsUnit = ['within', 'triggeredWithin'].includes(filter.operator);
|
||||||
|
|
||||||
@@ -208,45 +246,7 @@ const FilterRow = memo(function FilterRow({filter, onChange, onRemove, available
|
|||||||
|
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
setSearch('');
|
setSearch('');
|
||||||
}, [availableFields, filter.operator, fieldType, onChange]);
|
}, [availableFields, filter.operator, fieldType, onChange, getDefaultValueForType, getOperatorsForType]);
|
||||||
|
|
||||||
// Helper to get default value based on field type
|
|
||||||
const getDefaultValueForType = useCallback((type: string) => {
|
|
||||||
switch (type) {
|
|
||||||
case 'boolean':
|
|
||||||
return true;
|
|
||||||
case 'number':
|
|
||||||
return 0;
|
|
||||||
case 'date':
|
|
||||||
return '';
|
|
||||||
default:
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Helper to get valid operators for a field type
|
|
||||||
const getOperatorsForType = useCallback((type: string, isEvent: boolean) => {
|
|
||||||
if (isEvent) {
|
|
||||||
return EVENT_OPERATORS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'boolean') {
|
|
||||||
return STANDARD_OPERATORS.filter(op =>
|
|
||||||
['equals', 'notEquals', 'exists', 'notExists'].includes(op.value)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'number' || type === 'date') {
|
|
||||||
return STANDARD_OPERATORS.filter(op =>
|
|
||||||
['equals', 'notEquals', 'greaterThan', 'lessThan', 'greaterThanOrEqual', 'lessThanOrEqual', 'exists', 'notExists', 'within'].includes(op.value)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// String type - no within operator, no comparison operators
|
|
||||||
return STANDARD_OPERATORS.filter(op =>
|
|
||||||
['equals', 'notEquals', 'contains', 'notContains', 'exists', 'notExists'].includes(op.value)
|
|
||||||
);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Get label for selected field
|
// Get label for selected field
|
||||||
const getFieldLabel = useCallback(() => {
|
const getFieldLabel = useCallback(() => {
|
||||||
|
|||||||
@@ -334,6 +334,18 @@ export function WorkflowBuilder({workflowId, steps, onUpdate}: WorkflowBuilderPr
|
|||||||
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
|
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
|
||||||
const [stepToDelete, setStepToDelete] = useState<string | null>(null);
|
const [stepToDelete, setStepToDelete] = useState<string | null>(null);
|
||||||
|
|
||||||
|
// Define handlers before they are used in useMemo
|
||||||
|
const handleEditStep = useCallback((stepId: string) => {
|
||||||
|
// This will be handled by the parent component
|
||||||
|
const event = new CustomEvent('workflow-edit-step', {detail: {stepId}});
|
||||||
|
window.dispatchEvent(event);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleDeleteStepClick = useCallback((stepId: string) => {
|
||||||
|
setStepToDelete(stepId);
|
||||||
|
setShowDeleteDialog(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
// Convert workflow steps to React Flow nodes
|
// Convert workflow steps to React Flow nodes
|
||||||
|
|
||||||
const rawNodes: Node[] = useMemo(() => {
|
const rawNodes: Node[] = useMemo(() => {
|
||||||
@@ -622,17 +634,6 @@ export function WorkflowBuilder({workflowId, steps, onUpdate}: WorkflowBuilderPr
|
|||||||
[addStepContext, workflowId, onUpdate],
|
[addStepContext, workflowId, onUpdate],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleEditStep = useCallback((stepId: string) => {
|
|
||||||
// This will be handled by the parent component
|
|
||||||
const event = new CustomEvent('workflow-edit-step', {detail: {stepId}});
|
|
||||||
window.dispatchEvent(event);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleDeleteStepClick = useCallback((stepId: string) => {
|
|
||||||
setStepToDelete(stepId);
|
|
||||||
setShowDeleteDialog(true);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Get all steps that will be affected by deleting a step (the step itself + all downstream steps)
|
// Get all steps that will be affected by deleting a step (the step itself + all downstream steps)
|
||||||
const getAffectedSteps = useCallback(
|
const getAffectedSteps = useCallback(
|
||||||
(stepId: string): typeof steps => {
|
(stepId: string): typeof steps => {
|
||||||
|
|||||||
@@ -546,10 +546,6 @@ export default function CampaignDetailsPage() {
|
|||||||
setHasChanges(true);
|
setHasChanges(true);
|
||||||
}}
|
}}
|
||||||
placeholder="<h1>Welcome!</h1><p>Your email content here...</p>"
|
placeholder="<h1>Welcome!</h1><p>Your email content here...</p>"
|
||||||
canUploadImages={true}
|
|
||||||
subject={editedCampaign.subject}
|
|
||||||
from={editedCampaign.from}
|
|
||||||
replyTo={editedCampaign.replyTo || undefined}
|
|
||||||
/>
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -195,10 +195,6 @@ export default function CreateCampaignPage() {
|
|||||||
value={body}
|
value={body}
|
||||||
onChange={setBody}
|
onChange={setBody}
|
||||||
placeholder="<h1>Welcome!</h1><p>Your email content here...</p>"
|
placeholder="<h1>Welcome!</h1><p>Your email content here...</p>"
|
||||||
canUploadImages={true}
|
|
||||||
subject={subject}
|
|
||||||
from={from}
|
|
||||||
replyTo={replyTo}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
@@ -270,10 +270,6 @@ export default function TemplateEditorPage() {
|
|||||||
value={editedTemplate.body || ''}
|
value={editedTemplate.body || ''}
|
||||||
onChange={body => setEditedTemplate({...editedTemplate, body})}
|
onChange={body => setEditedTemplate({...editedTemplate, body})}
|
||||||
placeholder="<h1>Welcome!</h1><p>Thanks for subscribing to our newsletter.</p>"
|
placeholder="<h1>Welcome!</h1><p>Thanks for subscribing to our newsletter.</p>"
|
||||||
canUploadImages={true}
|
|
||||||
subject={editedTemplate.subject}
|
|
||||||
from={editedTemplate.from}
|
|
||||||
replyTo={editedTemplate.replyTo || undefined}
|
|
||||||
/>
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -179,10 +179,6 @@ export default function CreateTemplatePage() {
|
|||||||
value={body}
|
value={body}
|
||||||
onChange={setBody}
|
onChange={setBody}
|
||||||
placeholder="<h1>Welcome!</h1><p>Thanks for subscribing to our newsletter.</p>"
|
placeholder="<h1>Welcome!</h1><p>Thanks for subscribing to our newsletter.</p>"
|
||||||
canUploadImages={true}
|
|
||||||
subject={subject}
|
|
||||||
from={from}
|
|
||||||
replyTo={replyTo}
|
|
||||||
/>
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
/// <reference types="next" />
|
/// <reference types="next" />
|
||||||
/// <reference types="next/image-types/global" />
|
/// <reference types="next/image-types/global" />
|
||||||
import "./.next/dev/types/routes.d.ts";
|
import "./.next/types/routes.d.ts";
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
// NOTE: This file should not be edited
|
||||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||||
|
|||||||
@@ -36,14 +36,14 @@ const DialogContent = React.forwardRef<
|
|||||||
<DialogPrimitive.Content
|
<DialogPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-neutral-200 bg-white p-4 sm:p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] rounded-lg max-h-[90vh] overflow-y-auto mx-4 sm:mx-0',
|
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-neutral-200 bg-white p-4 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg max-h-[90vh] overflow-y-auto',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
<DialogPrimitive.Close className="absolute right-3 top-3 sm:right-4 sm:top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-neutral-100 data-[state=open]:text-neutral-500 p-1 sm:p-0">
|
<DialogPrimitive.Close className="absolute right-2.5 top-2.5 sm:right-4 sm:top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-neutral-100 data-[state=open]:text-neutral-500 p-1 sm:p-1.5">
|
||||||
<X className="h-5 w-5 sm:h-4 sm:w-4" />
|
<X className="h-5 w-5 sm:h-5 sm:w-5" />
|
||||||
<span className="sr-only">Close</span>
|
<span className="sr-only">Close</span>
|
||||||
</DialogPrimitive.Close>
|
</DialogPrimitive.Close>
|
||||||
</DialogPrimitive.Content>
|
</DialogPrimitive.Content>
|
||||||
|
|||||||
Reference in New Issue
Block a user