feat: configure ready outreach funnel limit

This commit is contained in:
jjbrunton committed 2026-08-09 16:13:58 +01:00
1 parent 22eb32e5bf
commit e9083281a8
15 files changed
+66 -11

No files matched your search

@@ -26,6 +26,7 @@ export interface SettingsDraft {
dryRun: boolean;
prioritizeRecentPosts: boolean;
recentWindowMinutes: string;
maxReadyCandidates: string;
subreddits: SubredditDraft[];
advancedConfigJson: string;
}
@@ -53,6 +54,7 @@ const ValidatedSettingsSchema = z.strictObject({
dryRun: z.boolean(),
prioritizeRecentPosts: z.boolean(),
recentWindowMinutes: z.number().finite().positive('Recent window must be greater than 0 minutes.'),
maxReadyCandidates: z.number().int().min(1, 'Ready-post limit must be at least 1.').max(500, 'Ready-post limit cannot exceed 500.'),
subreddits: z.array(EditableSubredditSchema).min(1, 'At least one subreddit is required.'),
}).superRefine((value, context) => {
const names = value.subreddits.map((subreddit) => subreddit.name.trim().toLowerCase());
@@ -69,6 +71,7 @@ export function createSettingsDraft(config: ConfigResponse): SettingsDraft {
dryRun: config.browser.dryRun,
prioritizeRecentPosts: config.reddit.prioritizeRecentPosts,
recentWindowMinutes: String(config.reddit.recentWindowMinutes),
maxReadyCandidates: String(config.reddit.maxReadyCandidates),
subreddits: config.subreddits.map((subreddit) => ({
name: subreddit.name,
enabled: subreddit.enabled,
@@ -90,6 +93,7 @@ export function validateSettingsDraft(draft: SettingsDraft): SettingsValidationR
if (draft.maxMessagesPerHour.trim() === '') requiredErrors.maxMessagesPerHour = 'Maximum messages per hour is required.';
if (draft.jitterSeconds.trim() === '') requiredErrors.jitterSeconds = 'Jitter is required.';
if (draft.recentWindowMinutes.trim() === '') requiredErrors.recentWindowMinutes = 'Recent window is required.';
if (draft.maxReadyCandidates.trim() === '') requiredErrors.maxReadyCandidates = 'Ready-post limit is required.';
draft.subreddits.forEach((subreddit, index) => {
if (subreddit.name.trim() === '') requiredErrors[`subreddits.${index}.name`] = 'Subreddit name is required.';
if (subreddit.weight.trim() !== '' && Number(subreddit.weight) <= 0) {
@@ -125,6 +129,7 @@ export function validateSettingsDraft(draft: SettingsDraft): SettingsValidationR
dryRun: draft.dryRun,
prioritizeRecentPosts: draft.prioritizeRecentPosts,
recentWindowMinutes: Number(draft.recentWindowMinutes),
maxReadyCandidates: Number(draft.maxReadyCandidates),
subreddits: draft.subreddits.map((subreddit) => ({
name: subreddit.name.trim(),
enabled: subreddit.enabled,
@@ -165,6 +170,7 @@ export function validateSettingsDraft(draft: SettingsDraft): SettingsValidationR
reddit: {
prioritizeRecentPosts: parsed.data.prioritizeRecentPosts,
recentWindowMinutes: parsed.data.recentWindowMinutes,
maxReadyCandidates: parsed.data.maxReadyCandidates,
},
subreddits: parsed.data.subreddits,
...(advanced ? { advanced } : {}),
@@ -58,6 +58,14 @@ export function MonitoringSection({ draft, errors, onChange }: SectionProps) {
onChange={(recentWindowMinutes) => onChange({ ...draft, recentWindowMinutes })}
value={draft.recentWindowMinutes}
/>
<NumberField
error={errors.maxReadyCandidates}
label="Maximum ready posts"
min={1}
name="maximum-ready-posts"
onChange={(maxReadyCandidates) => onChange({ ...draft, maxReadyCandidates })}
value={draft.maxReadyCandidates}
/>
</section>
);
}