Seth commited on
Commit ·
40ce77b
1
Parent(s): 30b1811
update
Browse files
frontend/src/components/campaigns/CampaignSequenceBuilder.jsx
CHANGED
|
@@ -196,18 +196,14 @@ function WaitCard({ step, onRemove, onDaysChange }) {
|
|
| 196 |
);
|
| 197 |
}
|
| 198 |
|
| 199 |
-
function ActionCard({ step,
|
| 200 |
const sender = (senderHint || '').trim();
|
| 201 |
const account = (accountHint || '').trim();
|
| 202 |
const showSender = sender && (!account || sender !== account);
|
| 203 |
const showLiMeta = step.channel === 'linkedin' && (showSender || account);
|
| 204 |
return (
|
| 205 |
<div className="relative w-full max-w-md">
|
| 206 |
-
<
|
| 207 |
-
type="button"
|
| 208 |
-
className="flex w-full items-center gap-3 rounded-xl border border-slate-200 bg-white px-4 py-3 text-left shadow-sm transition hover:border-slate-300 hover:bg-slate-50/80"
|
| 209 |
-
onClick={() => onConfigure?.(step)}
|
| 210 |
-
>
|
| 211 |
<ActionIcon action={step.action} />
|
| 212 |
<div className="min-w-0 flex-1">
|
| 213 |
<div className="flex items-start justify-between gap-2">
|
|
@@ -228,7 +224,7 @@ function ActionCard({ step, onConfigure, onRemove, senderHint, accountHint }) {
|
|
| 228 |
) : null}
|
| 229 |
</div>
|
| 230 |
<ChevronRight className="h-5 w-5 shrink-0 text-slate-300" aria-hidden />
|
| 231 |
-
</
|
| 232 |
{onRemove ? (
|
| 233 |
<button
|
| 234 |
type="button"
|
|
@@ -321,10 +317,6 @@ export default function CampaignSequenceBuilder({ value, onChange, linkedinDefau
|
|
| 321 |
<span className="inline-flex rounded-md bg-slate-100 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-slate-500">
|
| 322 |
Configure sequence
|
| 323 |
</span>
|
| 324 |
-
<p className="mt-2 text-sm text-slate-600">
|
| 325 |
-
Build your outreach flow. Use <strong>+</strong> to add emails, LinkedIn steps, or delays. LinkedIn steps
|
| 326 |
-
use your <strong>Settings → Connect LinkedIn</strong> profile name and default account when available.
|
| 327 |
-
</p>
|
| 328 |
{needsLinkedInConnection ? (
|
| 329 |
<p className="mt-2 rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-950">
|
| 330 |
Connect a LinkedIn account under Settings to execute LinkedIn steps in this sequence.
|
|
@@ -396,16 +388,6 @@ export default function CampaignSequenceBuilder({ value, onChange, linkedinDefau
|
|
| 396 |
)
|
| 397 |
: ''
|
| 398 |
}
|
| 399 |
-
onConfigure={(s) => {
|
| 400 |
-
const title = window.prompt('Step title', s.title);
|
| 401 |
-
if (title === null) return;
|
| 402 |
-
const subtitle = window.prompt('Description / preview', s.subtitle);
|
| 403 |
-
if (subtitle === null) return;
|
| 404 |
-
const next = steps.map((x, i) =>
|
| 405 |
-
i === index ? { ...x, title, subtitle } : x
|
| 406 |
-
);
|
| 407 |
-
setSteps(next);
|
| 408 |
-
}}
|
| 409 |
onRemove={() => removeAt(index)}
|
| 410 |
/>
|
| 411 |
)}
|
|
|
|
| 196 |
);
|
| 197 |
}
|
| 198 |
|
| 199 |
+
function ActionCard({ step, onRemove, senderHint, accountHint }) {
|
| 200 |
const sender = (senderHint || '').trim();
|
| 201 |
const account = (accountHint || '').trim();
|
| 202 |
const showSender = sender && (!account || sender !== account);
|
| 203 |
const showLiMeta = step.channel === 'linkedin' && (showSender || account);
|
| 204 |
return (
|
| 205 |
<div className="relative w-full max-w-md">
|
| 206 |
+
<div className="flex w-full items-center gap-3 rounded-xl border border-slate-200 bg-white px-4 py-3 text-left shadow-sm">
|
|
|
|
|
|
|
|
|
|
|
|
|
| 207 |
<ActionIcon action={step.action} />
|
| 208 |
<div className="min-w-0 flex-1">
|
| 209 |
<div className="flex items-start justify-between gap-2">
|
|
|
|
| 224 |
) : null}
|
| 225 |
</div>
|
| 226 |
<ChevronRight className="h-5 w-5 shrink-0 text-slate-300" aria-hidden />
|
| 227 |
+
</div>
|
| 228 |
{onRemove ? (
|
| 229 |
<button
|
| 230 |
type="button"
|
|
|
|
| 317 |
<span className="inline-flex rounded-md bg-slate-100 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-slate-500">
|
| 318 |
Configure sequence
|
| 319 |
</span>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 320 |
{needsLinkedInConnection ? (
|
| 321 |
<p className="mt-2 rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-950">
|
| 322 |
Connect a LinkedIn account under Settings to execute LinkedIn steps in this sequence.
|
|
|
|
| 388 |
)
|
| 389 |
: ''
|
| 390 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 391 |
onRemove={() => removeAt(index)}
|
| 392 |
/>
|
| 393 |
)}
|
frontend/src/components/campaigns/CreateCampaignWizard.jsx
CHANGED
|
@@ -225,9 +225,6 @@ export default function CreateCampaignWizard({ open, onOpenChange, onComplete })
|
|
| 225 |
<span className="inline-flex rounded-md bg-slate-100 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-slate-500">
|
| 226 |
Step 1
|
| 227 |
</span>
|
| 228 |
-
<p className="mt-2 text-sm text-slate-600">
|
| 229 |
-
Provide a name for your outreach campaign and upload your prospect list to begin.
|
| 230 |
-
</p>
|
| 231 |
</div>
|
| 232 |
<div>
|
| 233 |
<label className="mb-1.5 block text-sm font-medium text-slate-800">
|
|
@@ -277,10 +274,6 @@ export default function CreateCampaignWizard({ open, onOpenChange, onComplete })
|
|
| 277 |
<p className="mt-3 text-center text-sm font-semibold text-slate-800">
|
| 278 |
Drag and drop your CSV here
|
| 279 |
</p>
|
| 280 |
-
<p className="mt-1 max-w-md text-center text-xs text-slate-500">
|
| 281 |
-
Supported formats: .csv, .xlsx. Ensure your file contains headers for "Email",
|
| 282 |
-
"First Name", and "Company".
|
| 283 |
-
</p>
|
| 284 |
<Button
|
| 285 |
type="button"
|
| 286 |
variant="outline"
|
|
@@ -302,18 +295,6 @@ export default function CreateCampaignWizard({ open, onOpenChange, onComplete })
|
|
| 302 |
) : null}
|
| 303 |
</div>
|
| 304 |
</div>
|
| 305 |
-
<div className="flex flex-col gap-3 rounded-xl border border-violet-100 bg-violet-50/60 px-4 py-3 sm:flex-row sm:items-center sm:justify-between">
|
| 306 |
-
<p className="text-sm text-slate-700">
|
| 307 |
-
<span className="font-medium text-violet-900">Direct Apollo Sync.</span>{' '}
|
| 308 |
-
Want to skip the export? Connect your Apollo account in settings for direct lead importing.
|
| 309 |
-
</p>
|
| 310 |
-
<button
|
| 311 |
-
type="button"
|
| 312 |
-
className="shrink-0 text-sm font-semibold text-violet-700 hover:text-violet-900"
|
| 313 |
-
>
|
| 314 |
-
Configure Settings
|
| 315 |
-
</button>
|
| 316 |
-
</div>
|
| 317 |
</div>
|
| 318 |
) : step === 2 ? (
|
| 319 |
<CampaignSequenceBuilder
|
|
|
|
| 225 |
<span className="inline-flex rounded-md bg-slate-100 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-slate-500">
|
| 226 |
Step 1
|
| 227 |
</span>
|
|
|
|
|
|
|
|
|
|
| 228 |
</div>
|
| 229 |
<div>
|
| 230 |
<label className="mb-1.5 block text-sm font-medium text-slate-800">
|
|
|
|
| 274 |
<p className="mt-3 text-center text-sm font-semibold text-slate-800">
|
| 275 |
Drag and drop your CSV here
|
| 276 |
</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 277 |
<Button
|
| 278 |
type="button"
|
| 279 |
variant="outline"
|
|
|
|
| 295 |
) : null}
|
| 296 |
</div>
|
| 297 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 298 |
</div>
|
| 299 |
) : step === 2 ? (
|
| 300 |
<CampaignSequenceBuilder
|
frontend/src/components/settings/LinkedInConnectSettings.jsx
CHANGED
|
@@ -94,12 +94,6 @@ export default function LinkedInConnectSettings() {
|
|
| 94 |
Refresh
|
| 95 |
</Button>
|
| 96 |
</div>
|
| 97 |
-
<p className="mt-2 text-sm text-slate-600">
|
| 98 |
-
Connect your LinkedIn with secure hosted authentication (no password stored here). After you connect, we pull
|
| 99 |
-
your <strong>LinkedIn profile name</strong> from the account and use it in campaigns together with your
|
| 100 |
-
default connection.
|
| 101 |
-
</p>
|
| 102 |
-
|
| 103 |
<div className="mt-4 grid gap-3 md:grid-cols-2">
|
| 104 |
<div>
|
| 105 |
<label className="mb-1 block text-xs font-medium text-slate-600">LinkedIn profile name</label>
|
|
@@ -120,10 +114,6 @@ export default function LinkedInConnectSettings() {
|
|
| 120 |
/>
|
| 121 |
</div>
|
| 122 |
</div>
|
| 123 |
-
<p className="mt-2 text-xs text-slate-500">
|
| 124 |
-
Redirect-based hosted auth — credentials never touch this app.
|
| 125 |
-
</p>
|
| 126 |
-
|
| 127 |
<div className="mt-4 flex flex-wrap gap-2">
|
| 128 |
<Button type="button" disabled={busy} onClick={savePreferences} variant="outline">
|
| 129 |
{busy ? <Loader2 className="h-4 w-4 animate-spin" /> : 'Save preferences'}
|
|
@@ -193,9 +183,6 @@ export default function LinkedInConnectSettings() {
|
|
| 193 |
})}
|
| 194 |
</ul>
|
| 195 |
<div className="flex flex-wrap items-center gap-3">
|
| 196 |
-
<p className="text-xs text-slate-500">
|
| 197 |
-
Select a default account, then <strong>Save preferences</strong>.
|
| 198 |
-
</p>
|
| 199 |
<button
|
| 200 |
type="button"
|
| 201 |
className="text-xs font-medium text-violet-700 hover:underline"
|
|
|
|
| 94 |
Refresh
|
| 95 |
</Button>
|
| 96 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
<div className="mt-4 grid gap-3 md:grid-cols-2">
|
| 98 |
<div>
|
| 99 |
<label className="mb-1 block text-xs font-medium text-slate-600">LinkedIn profile name</label>
|
|
|
|
| 114 |
/>
|
| 115 |
</div>
|
| 116 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
<div className="mt-4 flex flex-wrap gap-2">
|
| 118 |
<Button type="button" disabled={busy} onClick={savePreferences} variant="outline">
|
| 119 |
{busy ? <Loader2 className="h-4 w-4 animate-spin" /> : 'Save preferences'}
|
|
|
|
| 183 |
})}
|
| 184 |
</ul>
|
| 185 |
<div className="flex flex-wrap items-center gap-3">
|
|
|
|
|
|
|
|
|
|
| 186 |
<button
|
| 187 |
type="button"
|
| 188 |
className="text-xs font-medium text-violet-700 hover:underline"
|