Seth commited on
Commit
2ba39f6
·
1 Parent(s): bdec327
frontend/src/components/campaigns/CampaignSequenceBuilder.jsx CHANGED
@@ -196,11 +196,13 @@ function WaitCard({ step, onRemove, onDaysChange }) {
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">
@@ -222,6 +224,9 @@ function ActionCard({ step, onRemove, senderHint, accountHint }) {
222
  {account ? <span>Profile: {account}</span> : null}
223
  </p>
224
  ) : null}
 
 
 
225
  </div>
226
  <ChevronRight className="h-5 w-5 shrink-0 text-slate-300" aria-hidden />
227
  </div>
@@ -245,7 +250,7 @@ function ActionCard({ step, onRemove, senderHint, accountHint }) {
245
  /**
246
  * Vertical sequence builder: START → steps (+ inserts) → END with dashed spine.
247
  */
248
- export default function CampaignSequenceBuilder({ value, onChange, linkedinDefaults }) {
249
  const steps = value;
250
  const setSteps = onChange;
251
  const [pickerIndex, setPickerIndex] = useState(null);
@@ -260,6 +265,14 @@ export default function CampaignSequenceBuilder({ value, onChange, linkedinDefau
260
  },
261
  [linkedinDefaults]
262
  );
 
 
 
 
 
 
 
 
263
 
264
  const insertAt = useCallback(
265
  (index, kind) => {
@@ -388,6 +401,17 @@ export default function CampaignSequenceBuilder({ value, onChange, linkedinDefau
388
  )
389
  : ''
390
  }
 
 
 
 
 
 
 
 
 
 
 
391
  onRemove={() => removeAt(index)}
392
  />
393
  )}
 
196
  );
197
  }
198
 
199
+ function ActionCard({ step, onRemove, senderHint, accountHint, emailAccountHint }) {
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
+ const mailbox = (emailAccountHint || '').trim();
205
+ const showEmailMeta = step.channel === 'gmail' && !!mailbox;
206
  return (
207
  <div className="relative w-full max-w-md">
208
  <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">
 
224
  {account ? <span>Profile: {account}</span> : null}
225
  </p>
226
  ) : null}
227
+ {showEmailMeta ? (
228
+ <p className="mt-1 text-[11px] leading-snug text-violet-700">Mailbox: {mailbox}</p>
229
+ ) : null}
230
  </div>
231
  <ChevronRight className="h-5 w-5 shrink-0 text-slate-300" aria-hidden />
232
  </div>
 
250
  /**
251
  * Vertical sequence builder: START → steps (+ inserts) → END with dashed spine.
252
  */
253
+ export default function CampaignSequenceBuilder({ value, onChange, linkedinDefaults, mailboxDefaults }) {
254
  const steps = value;
255
  const setSteps = onChange;
256
  const [pickerIndex, setPickerIndex] = useState(null);
 
265
  },
266
  [linkedinDefaults]
267
  );
268
+ const mailboxLabelFor = useCallback(
269
+ (refId) => {
270
+ if (refId == null) return '';
271
+ const a = mailboxDefaults?.accounts?.find((x) => Number(x.id) === Number(refId));
272
+ return (a?.display_name || a?.label || '').trim();
273
+ },
274
+ [mailboxDefaults]
275
+ );
276
 
277
  const insertAt = useCallback(
278
  (index, kind) => {
 
401
  )
402
  : ''
403
  }
404
+ emailAccountHint={
405
+ step.channel === 'gmail'
406
+ ? (
407
+ mailboxLabelFor(
408
+ step.unipile_account_ref_id ??
409
+ mailboxDefaults?.default_mailbox_unipile_account_ref_id
410
+ ) ||
411
+ (mailboxDefaults?.mailbox_profile_display_name || '').trim()
412
+ )
413
+ : ''
414
+ }
415
  onRemove={() => removeAt(index)}
416
  />
417
  )}
frontend/src/components/campaigns/CreateCampaignWizard.jsx CHANGED
@@ -36,6 +36,7 @@ export default function CreateCampaignWizard({ open, onOpenChange, onComplete })
36
  const [estimatedContacts, setEstimatedContacts] = useState(0);
37
  const [sequenceSteps, setSequenceSteps] = useState(() => createDefaultSequenceSteps());
38
  const [linkedinDefaults, setLinkedinDefaults] = useState(null);
 
39
 
40
  const reset = useCallback(() => {
41
  setStep(1);
@@ -76,23 +77,34 @@ export default function CreateCampaignWizard({ open, onOpenChange, onComplete })
76
  useEffect(() => {
77
  if (!open) {
78
  setLinkedinDefaults(null);
 
79
  return;
80
  }
81
  let cancelled = false;
82
- apiFetch('/api/unipile/linkedin/campaign-defaults')
83
- .then((r) => r.json())
84
- .then((d) => {
85
- if (!cancelled) setLinkedinDefaults(d);
86
- })
87
- .catch(() => {
88
- if (!cancelled) {
89
- setLinkedinDefaults({
90
- accounts: [],
91
- linkedin_profile_display_name: '',
92
- default_unipile_account_ref_id: null,
93
- });
94
- }
95
- });
 
 
 
 
 
 
 
 
 
 
96
  return () => {
97
  cancelled = true;
98
  };
@@ -301,6 +313,7 @@ export default function CreateCampaignWizard({ open, onOpenChange, onComplete })
301
  value={sequenceSteps}
302
  onChange={setSequenceSteps}
303
  linkedinDefaults={linkedinDefaults}
 
304
  />
305
  ) : step === 3 ? (
306
  <PlaceholderStep
 
36
  const [estimatedContacts, setEstimatedContacts] = useState(0);
37
  const [sequenceSteps, setSequenceSteps] = useState(() => createDefaultSequenceSteps());
38
  const [linkedinDefaults, setLinkedinDefaults] = useState(null);
39
+ const [mailboxDefaults, setMailboxDefaults] = useState(null);
40
 
41
  const reset = useCallback(() => {
42
  setStep(1);
 
77
  useEffect(() => {
78
  if (!open) {
79
  setLinkedinDefaults(null);
80
+ setMailboxDefaults(null);
81
  return;
82
  }
83
  let cancelled = false;
84
+ Promise.allSettled([
85
+ apiFetch('/api/unipile/linkedin/campaign-defaults').then((r) => r.json()),
86
+ apiFetch('/api/unipile/mailbox/campaign-defaults').then((r) => r.json()),
87
+ ]).then(([li, mb]) => {
88
+ if (cancelled) return;
89
+ setLinkedinDefaults(
90
+ li.status === 'fulfilled'
91
+ ? li.value
92
+ : {
93
+ accounts: [],
94
+ linkedin_profile_display_name: '',
95
+ default_unipile_account_ref_id: null,
96
+ }
97
+ );
98
+ setMailboxDefaults(
99
+ mb.status === 'fulfilled'
100
+ ? mb.value
101
+ : {
102
+ accounts: [],
103
+ mailbox_profile_display_name: '',
104
+ default_mailbox_unipile_account_ref_id: null,
105
+ }
106
+ );
107
+ });
108
  return () => {
109
  cancelled = true;
110
  };
 
313
  value={sequenceSteps}
314
  onChange={setSequenceSteps}
315
  linkedinDefaults={linkedinDefaults}
316
+ mailboxDefaults={mailboxDefaults}
317
  />
318
  ) : step === 3 ? (
319
  <PlaceholderStep