Add account browsing simulation
This commit is contained in:
1 parent
e2d7dc4b82
commit
27012399ec
31 files changed
+1476
-28
No files matched your search
@@ -5,6 +5,7 @@ import {
|
||||
GrowthOverviewResponseSchema,
|
||||
type GrowthAccountDetail,
|
||||
type GrowthAccountSummary,
|
||||
type BrowsingSettingsUpdateRequest,
|
||||
type GrowthSettingsUpdateRequest,
|
||||
type GrowthSubredditCreateRequest,
|
||||
type GrowthSubredditUpdateRequest,
|
||||
@@ -50,6 +51,19 @@ export function updateGrowthSettings(
|
||||
.then((payload) => payload.account);
|
||||
}
|
||||
|
||||
export function updateBrowsingSettings(
|
||||
accountId: string,
|
||||
update: BrowsingSettingsUpdateRequest,
|
||||
): Promise<GrowthAccountDetail> {
|
||||
return dashboardRequest(`${accountPath(accountId)}/browsing`, {
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(update),
|
||||
})
|
||||
.then((response) => parseResponse(response, GrowthAccountResponseSchema))
|
||||
.then((payload) => payload.account);
|
||||
}
|
||||
|
||||
export function pauseGrowth(accountId: string, reason?: string): Promise<GrowthAccountDetail> {
|
||||
return dashboardRequest(`${accountPath(accountId)}/pause`, {
|
||||
method: 'POST',
|
||||
|
||||
@@ -4,6 +4,7 @@ import type {
|
||||
GrowthAccountSummary,
|
||||
GrowthComment,
|
||||
GrowthSubreddit,
|
||||
BrowsingDecision,
|
||||
} from '../../../../../packages/api-contracts/src/index.js';
|
||||
import { NumberField, SwitchField, TextField } from '../../components/form-fields.js';
|
||||
import { RedditUsernameLink } from '../../components/reddit-username-link.js';
|
||||
@@ -15,6 +16,7 @@ import {
|
||||
useRemoveGrowthSubredditMutation,
|
||||
useResumeGrowthMutation,
|
||||
useUpdateGrowthSettingsMutation,
|
||||
useUpdateBrowsingSettingsMutation,
|
||||
useUpdateGrowthSubredditMutation,
|
||||
} from './growth-queries.js';
|
||||
import './growth.css';
|
||||
@@ -170,6 +172,68 @@ function SubredditRow({
|
||||
);
|
||||
}
|
||||
|
||||
function BrowsingSimulationSection({ account }: { account: GrowthAccountDetail }) {
|
||||
const update = useUpdateBrowsingSettingsMutation(account.accountId);
|
||||
const { settings, stats, todayTarget, recentDecisions } = account.browsing;
|
||||
const selected = recentDecisions.filter((decision) => decision.decision === 'simulated-upvote');
|
||||
|
||||
return (
|
||||
<section aria-labelledby="browsing-simulation-heading" className="panel settings-card">
|
||||
<div className="settings-card-heading">
|
||||
<div>
|
||||
<span className="eyebrow">Simulation only</span>
|
||||
<h2 id="browsing-simulation-heading">Browsing simulation</h2>
|
||||
<p>Tests selection and pacing without submitting votes or any other Reddit write.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-card-body">
|
||||
<div className="state-banner is-warning" role="status">
|
||||
<strong>No Reddit votes were submitted.</strong>
|
||||
<span>Every item below is a hypothetical upvote recorded only in RedditBot.</span>
|
||||
</div>
|
||||
<SwitchField
|
||||
checked={settings.enabled}
|
||||
description={`Selects ${settings.dailyTargetMin}–${settings.dailyTargetMax} eligible posts or comments during waking hours.`}
|
||||
label="Simulate browsing selections"
|
||||
onChange={(enabled) => update.mutate({ enabled })}
|
||||
/>
|
||||
<dl className="growth-metrics">
|
||||
<div><dt>Selected today</dt><dd>{stats.selected} / {todayTarget}</dd></div>
|
||||
<div><dt>Posts</dt><dd>{stats.posts}</dd></div>
|
||||
<div><dt>Comments</dt><dd>{stats.comments}</dd></div>
|
||||
<div><dt>Rejected</dt><dd>{stats.rejected}</dd></div>
|
||||
<div><dt>Skipped</dt><dd>{stats.skipped}</dd></div>
|
||||
<div>
|
||||
<dt>Next session</dt>
|
||||
<dd>{settings.nextDueAt === null ? 'Not scheduled' : new Date(settings.nextDueAt).toLocaleString()}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
{update.isError ? <p className="save-error" role="alert">{errorMessage(update.error)}</p> : null}
|
||||
{selected.length === 0 ? (
|
||||
<div className="empty-state">
|
||||
<strong>No simulated selections yet</strong>
|
||||
<span>The first session is durably scheduled after this feature is enabled.</span>
|
||||
</div>
|
||||
) : (
|
||||
<ul className="growth-comment-list">
|
||||
{selected.map((decision: BrowsingDecision) => (
|
||||
<li className="growth-comment" key={`${decision.thingFullname}-${decision.decidedAt}`}>
|
||||
<div className="growth-comment-head">
|
||||
<a href={`https://www.reddit.com${decision.permalink}`} rel="noreferrer noopener" target="_blank">
|
||||
r/{decision.subreddit} — {decision.thingKind} by u/{decision.author}
|
||||
</a>
|
||||
<span className="pill neutral">Simulated upvote</span>
|
||||
</div>
|
||||
<p className="field-hint">{new Date(decision.decidedAt).toLocaleString()}</p>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function AccountDetail({ account }: { account: GrowthAccountDetail }) {
|
||||
const { accountId, settings, stats } = account;
|
||||
const updateSettings = useUpdateGrowthSettingsMutation(accountId);
|
||||
@@ -435,6 +499,8 @@ function AccountDetail({ account }: { account: GrowthAccountDetail }) {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<BrowsingSimulationSection account={account} />
|
||||
|
||||
<section aria-labelledby="growth-history-heading" className="panel settings-card">
|
||||
<div className="settings-card-heading">
|
||||
<div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import type {
|
||||
GrowthAccountDetail,
|
||||
BrowsingSettingsUpdateRequest,
|
||||
GrowthSettingsUpdateRequest,
|
||||
GrowthSubredditCreateRequest,
|
||||
GrowthSubredditUpdateRequest,
|
||||
@@ -13,6 +14,7 @@ import {
|
||||
removeGrowthSubreddit,
|
||||
resumeGrowth,
|
||||
updateGrowthSettings,
|
||||
updateBrowsingSettings,
|
||||
updateGrowthSubreddit,
|
||||
} from './growth-api.js';
|
||||
|
||||
@@ -63,6 +65,13 @@ export function useUpdateGrowthSettingsMutation(accountId: string) {
|
||||
);
|
||||
}
|
||||
|
||||
export function useUpdateBrowsingSettingsMutation(accountId: string) {
|
||||
return useGrowthMutation(
|
||||
accountId,
|
||||
(update: BrowsingSettingsUpdateRequest) => updateBrowsingSettings(accountId, update),
|
||||
);
|
||||
}
|
||||
|
||||
export function usePauseGrowthMutation(accountId: string) {
|
||||
return useGrowthMutation(accountId, (reason?: string) => pauseGrowth(accountId, reason));
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user