brackt/app/components/league/settings/NotificationsSection.tsx
Chris Parsons fbcecb490e
Add Discord draft pick announcements (#460)
* Add Discord draft pick announcements

Posts a message to the league Discord webhook each time a pick is made, announcing the picked participant and pinging the next team on the clock if their owner has opted into Discord notifications. Enabled via a separate toggle in league settings (independent from standings update notifications).

https://claude.ai/code/session_01Tvwsv3LfL9JUqxoLct8dTn

* Address code review feedback on Discord pick announcements

- Fix "on the clock" timing: read currentPickNumber fresh from DB post-autodraft-chain (matches sendOnTheClockEmail guarantee)
- Remove outer try/catch from notifyPickMadeOnDiscord so callers' .catch() is not dead code
- Add missing draft-discord.server.test.ts with 12 tests covering all early-exit and happy paths
- Fix silent empty-string fallback for missing pickedSlot: warn and skip instead
- Eliminate sequential season→league DB queries by accepting leagueId as a direct param
- Show "save webhook URL to configure options" hint when URL is typed but not yet saved
- Remove block-scope braces at both call sites (plain const declarations)
- Remove redundant "Round N, Pick M" description line (title already carries this info)
- Inline pickInRoundFor helper to avoid circular import with draft-utils

https://claude.ai/code/session_01Tvwsv3LfL9JUqxoLct8dTn

* Fix lint errors from review fixes

- Remove unused logger import (no longer needed after removing try/catch)
- Remove unused OWNER_ID constant in test fixture
- Use toSorted() instead of sort() in sendDraftOrderNotification

https://claude.ai/code/session_01Tvwsv3LfL9JUqxoLct8dTn

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-05-20 19:55:48 -07:00

71 lines
2.7 KiB
TypeScript

import { Bell } from "lucide-react";
import { Input } from "~/components/ui/input";
import { Label } from "~/components/ui/label";
import { Switch } from "~/components/ui/switch";
import { SettingsSection, SettingsStatusPill } from "./SettingsSection";
export function NotificationsSection({
active,
savedDiscordWebhookUrl,
discordWebhookUrl,
onDiscordWebhookUrlChange,
discordPicksAnnouncementEnabled,
onDiscordPicksAnnouncementEnabledChange,
}: {
active: boolean;
savedDiscordWebhookUrl: string | null;
discordWebhookUrl: string;
onDiscordWebhookUrlChange: (v: string) => void;
discordPicksAnnouncementEnabled: boolean;
onDiscordPicksAnnouncementEnabledChange: (v: boolean) => void;
}) {
return (
<SettingsSection
id="notifications"
icon={Bell}
title="Notifications"
description="Send Discord alerts when standings change after scoring events."
status={<SettingsStatusPill tone={savedDiscordWebhookUrl ? "success" : "warning"}>{savedDiscordWebhookUrl ? "Configured" : "Optional"}</SettingsStatusPill>}
className={active ? undefined : "hidden"}
>
<div className="space-y-4">
<div className="space-y-2">
<Label htmlFor="discordWebhookUrl">Discord Webhook URL</Label>
<Input
id="discordWebhookUrl"
name="discordWebhookUrl"
type="url"
value={discordWebhookUrl}
onChange={(e) => onDiscordWebhookUrlChange(e.target.value)}
placeholder="https://discord.com/api/webhooks/..."
/>
<p className="text-sm text-muted-foreground">
Create a webhook in Discord under Server Settings, Integrations, Webhooks.
</p>
</div>
{savedDiscordWebhookUrl ? (
<div className="flex items-center gap-3">
<Switch
id="discordPicksAnnouncementEnabled"
name="discordPicksAnnouncementEnabled"
checked={discordPicksAnnouncementEnabled}
onCheckedChange={onDiscordPicksAnnouncementEnabledChange}
/>
<div>
<Label htmlFor="discordPicksAnnouncementEnabled" className="cursor-pointer">
Announce draft picks
</Label>
<p className="text-sm text-muted-foreground">
Post a message for each pick and ping the next team's owner if they've enabled Discord notifications.
</p>
</div>
</div>
) : discordWebhookUrl ? (
<p className="text-sm text-muted-foreground">
Save the webhook URL above to configure additional notification options.
</p>
) : null}
</div>
</SettingsSection>
);
}