PageSourceSearch

https://lcplunderground.vet/assets/raffle-K8jwzCK3.js

js lcplunderground.vet collected 2026-10-10 00:53:17 UTC 29,639 bytes, 394 lines download raw bytes

1import { r as reactExports, j as jsxRuntimeExports, dV as Medal, v as AnimatePresence, w as motion, a5 as Trophy, m as Calendar, z as Users, cb as Ticket, aC as Helmet, b1 as Gift, ae as Lock, dW as UserX, a$ as CircleCheckBig, aY as ChevronUp, ah as ChevronDown } from "./vendor-BRPG2tLG.js";
2import { M as MemberGate } from "./MemberGate--WQNiOYv.js";
3import { C as Card, b as CardHeader, c as CardTitle, a as CardContent } from "./card--K7fotj0.js";
4import { B as Badge } from "./badge-BgHhs2gV.js";
5import { aG as raffle_announcement, aE as raffle_winner_controls, bY as TIER_CONFIG, bZ as getTier } from "./index-DVj0zJ6X.js";
6import "./preload-D9ItKcgK.js";
7function formatDate(iso) {
8  return new Date(iso).toLocaleDateString("en-US", {
9    month: "long",
10    day: "numeric",
11    year: "numeric"
12  });
13}
14function LotteryHallOfFame() {
15  const [winners, setWinners] = reactExports.useState([]);
16  const [loading, setLoading] = reactExports.useState(true);
17  reactExports.useEffect(() => {
18    fetch("/api/raffle/winners").then((r) => r.json()).then((d) => {
19      setWinners(d.winners ?? []);
20      setLoading(false);
21    }).catch(() => setLoading(false));
22  }, []);
23  if (loading) {
24    return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-3 mt-2", children: [1, 2].map((i) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-24 rounded-xl bg-muted animate-pulse" }, i)) });
25  }
26  if (winners.length === 0) {
27    return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center py-10 text-muted-foreground", children: [
28      /* @__PURE__ */ jsxRuntimeExports.jsx(Medal, { className: "h-8 w-8 mx-auto mb-2 opacity-30" }),
29      /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm", children: "No winners announced yet — be the first." })
30    ] });
31  }
32  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-3", children: /* @__PURE__ */ jsxRuntimeExports.jsx(AnimatePresence, { initial: false, children: winners.map((w, i) => /* @__PURE__ */ jsxRuntimeExports.jsx(motion.div, { initial: {
33    opacity: 0,
34    y: 12
35  }, animate: {
36    opacity: 1,
37    y: 0
38  }, transition: {
39    duration: 0.3,
40    delay: i * 0.06,
41    ease: "easeOut"
42  }, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-xl border border-border bg-card overflow-hidden flex gap-0", children: [
43    w.imageUrl && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-20 shrink-0 hidden sm:block", children: /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: w.imageUrl, alt: w.prize, className: "w-full h-full object-cover", loading: "lazy" }) }),
44    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 px-4 py-3 space-y-1.5", children: [
45      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
46        /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1.5 bg-primary/10 text-primary border border-primary/20 rounded-full px-3 py-0.5 text-sm font-bold", children: [
47          /* @__PURE__ */ jsxRuntimeExports.jsx(Trophy, { className: "h-3.5 w-3.5" }),
48          w.winnerDisplayName
49        ] }),
50        w.winnerMemberNumber !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs text-muted-foreground font-mono", children: [
51          "Member #",
52          w.winnerMemberNumber
53        ] })
54      ] }),
55      /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-semibold text-foreground leading-tight", children: w.prize }),
56      /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: w.raffleTitle }),
57      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 text-xs text-muted-foreground flex-wrap pt-0.5", children: [
58        /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1", children: [
59          /* @__PURE__ */ jsxRuntimeExports.jsx(Calendar, { className: "h-3 w-3" }),
60          formatDate(w.drawnAt)
61        ] }),
62        /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1", children: [
63          /* @__PURE__ */ jsxRuntimeExports.jsx(Users, { className: "h-3 w-3" }),
64          w.entryCount.toLocaleString(),
65          " ",
66          w.entryCount === 1 ? "entry" : "entries"
67        ] }),
68        /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1", children: [
69          /* @__PURE__ */ jsxRuntimeExports.jsx(Ticket, { className: "h-3 w-3" }),
70          "1-in-",
71          w.entryCount,
72          " odds"
73        ] })
74      ] })
75    ] })
76  ] }) }, w.raffleId)) }) });
77}
78const STATUS_LABELS = {
79  open: {
80    label: "Draw Upcoming",
81    color: "bg-green-600 text-white"
82  },
83  closed: {
84    label: "Drawing Soon",
85    color: "bg-yellow-500 text-black"
86  },
87  drawn: {
88    label: "Winner Drawn",
89    color: "bg-primary text-primary-foreground"
90  },
91  draft: {
92    label: "Coming Soon",
93    color: "bg-muted text-muted-foreground"
94  }
95};
96function RafflePage() {
97  const [raffles, setRaffles] = reactExports.useState([]);
98  const [loading, setLoading] = reactExports.useState(true);
99  const [optedOut, setOptedOut] = reactExports.useState(false);
100  const [loggedIn, setLoggedIn] = reactExports.useState(false);
101  const [isStaff, setIsStaff] = reactExports.useState(false);
102  const [showHallOfFame, setShowHallOfFame] = reactExports.useState(false);
103  const [winnerRecords, setWinnerRecords] = reactExports.useState([]);
104  const [savingWinnerId, setSavingWinnerId] = reactExports.useState(null);
105  const [winnerChoiceError, setWinnerChoiceError] = reactExports.useState("");
106  reactExports.useEffect(() => {
107    fetch("/api/profile", {
108      credentials: "include"
109    }).then((r) => r.ok ? r.json() : null).then((d) => {
110      if (d == null ? void 0 : d.profile) {
111        setLoggedIn(true);
112        const raw = d.profile;
113        setOptedOut(raw.lottery_opt_out === 1 || raw.lottery_opt_out === true);
114        setIsStaff(!!(raw.is_admin || raw.is_moderator || raw.is_owner));
115      }
116    }).catch(() => {
117    });
118    fetch("/api/raffle", {
119      credentials: "include"
120    }).then((r) => r.json()).then((d) => {
121      setRaffles(d.raffles ?? []);
122      setLoading(false);
123    });
124    fetch("/api/raffle/my-wins", {
125      credentials: "include"
126    }).then((r) => r.ok ? r.json() : {
127      wins: []
128    }).then((d) => setWinnerRecords(d.wins ?? [])).catch(() => setWinnerRecords([]));
129  }, []);
130  async function saveWinnerPrivacy(raffleId, choice) {
131    setSavingWinnerId(raffleId);
132    setWinnerChoiceError("");
133    try {
134      const response = await fetch("/api/raffle/winner-privacy", {
135        method: "POST",
136        credentials: "include",
137        headers: {
138          "Content-Type": "application/json"
139        },
140        body: JSON.stringify({
141          raffleId,
142          choice
143        })
144      });
145      if (!response.ok) throw new Error();
146      setWinnerRecords((records) => records.map((record) => record.raffle_id === raffleId ? {
147        ...record,
148        public_identity_consent: choice
149      } : record));
150    } catch {
151      setWinnerChoiceError(raffle_winner_controls.winnerCenter.saveError);
152    } finally {
153      setSavingWinnerId(null);
154    }
155  }
156  return /* @__PURE__ */ jsxRuntimeExports.jsx(MemberGate, { toolName: "Member Lottery", toolDescription: "Active members are automatically entered to win veteran gear and commemorative items. Free to enter — just show up.", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(Trophy, { className: "h-8 w-8 text-primary" }), children: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
157    /* @__PURE__ */ jsxRuntimeExports.jsxs(Helmet, { children: [
158      /* @__PURE__ */ jsxRuntimeExports.jsx("title", { children: "Member Lottery — Win Veteran Gear & Commemorative Items | LCplUnderground.Vet" }),
159      /* @__PURE__ */ jsxRuntimeExports.jsx("meta", { name: "description", content: "Every registered member is automatically entered in member-exclusive raffles for a chance to win challenge coins, athletic shirts, commemorative medals, and more." }),
160      /* @__PURE__ */ jsxRuntimeExports.jsx("link", { rel: "canonical", href: "https://lcplunderground.vet/raffle" }),
161      /* @__PURE__ */ jsxRuntimeExports.jsx("meta", { property: "og:type", content: "website" }),
162      /* @__PURE__ */ jsxRuntimeExports.jsx("meta", { property: "og:site_name", content: "LCplUnderground.Vet" }),
163      /* @__PURE__ */ jsxRuntimeExports.jsx("meta", { property: "og:url", content: "https://lcplunderground.vet/raffle" }),
164      /* @__PURE__ */ jsxRuntimeExports.jsx("meta", { property: "og:title", content: "Member Lottery — Win Veteran Gear & Commemorative Items" }),
165      /* @__PURE__ */ jsxRuntimeExports.jsx("meta", { property: "og:description", content: "Every registered member is automatically entered in member-exclusive raffles for a chance to win challenge coins, shirts, commemorative medals, and more." }),
166      /* @__PURE__ */ jsxRuntimeExports.jsx("meta", { property: "og:image", content: "https://lcplunderground.vet/og-default.png" }),
167      /* @__PURE__ */ jsxRuntimeExports.jsx("meta", { name: "twitter:card", content: "summary_large_image" }),
168      /* @__PURE__ */ jsxRuntimeExports.jsx("meta", { name: "twitter:site", content: "@LCplUnderground" }),
169      /* @__PURE__ */ jsxRuntimeExports.jsx("meta", { name: "twitter:title", content: "Member Lottery — Win Veteran Gear | LCplUnderground.Vet" }),
170      /* @__PURE__ */ jsxRuntimeExports.jsx("meta", { name: "twitter:description", content: "Every registered member is automatically entered in member-exclusive raffles for challenge coins, shirts, and more." }),
171      /* @__PURE__ */ jsxRuntimeExports.jsx("meta", { name: "twitter:image", content: "https://lcplunderground.vet/og-default.png" }),
172      /* @__PURE__ */ jsxRuntimeExports.jsx("script", { type: "application/ld+json", children: JSON.stringify({
173        "@context": "https://schema.org",
174        "@type": "WebPage",
175        "name": "Member Lottery — LCplUnderground.Vet",
176        "url": "https://lcplunderground.vet/raffle",
177        "description": "Member-exclusive raffles for veteran gear, challenge coins, and commemorative items. Every registered member is automatically entered.",
178        "publisher": {
179          "@type": "Organization",
180          "name": "LCplUnderground.Vet",
181          "url": "https://lcplunderground.vet"
182        }
183      }) })
184    ] }),
185    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-3xl mx-auto px-4 py-12", children: [
186      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 mb-2", children: [
187        /* @__PURE__ */ jsxRuntimeExports.jsx(Gift, { className: "h-8 w-8 text-primary" }),
188        /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { className: "text-3xl font-bold tracking-tight", children: "Member Lottery" })
189      ] }),
190      /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground mb-6", children: "Every registered member is automatically entered. Your member number is your ticket — no action required. Winners are drawn on the scheduled date and announced on the Events page." }),
191      /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { "aria-labelledby": "fair-draw", className: "mb-8 rounded-xl border border-border bg-muted p-5", children: [
192        /* @__PURE__ */ jsxRuntimeExports.jsx("section", { "aria-labelledby": "first-member-recognition", className: "mb-4 rounded-xl border border-primary bg-card p-5", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-3", children: [
193          /* @__PURE__ */ jsxRuntimeExports.jsx(Medal, { className: "mt-0.5 h-5 w-5 shrink-0 text-primary", "aria-hidden": "true" }),
194          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
195            /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { id: "first-member-recognition", className: "text-lg font-bold", style: {
196              whiteSpace: "pre-line"
197            }, children: raffle_announcement.recognition.heading }),
198            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-1 text-sm text-muted-foreground", style: {
199              whiteSpace: "pre-line"
200            }, children: raffle_announcement.recognition.body })
201          ] })
202        ] }) }),
203        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-3", children: [
204          /* @__PURE__ */ jsxRuntimeExports.jsx(Ticket, { className: "mt-0.5 h-5 w-5 shrink-0 text-primary", "aria-hidden": "true" }),
205          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
206            /* @__P
206URE__ */ jsxRuntimeExports.jsx("h2", { id: "fair-draw", className: "text-lg font-bold", style: {
207              whiteSpace: "pre-line"
208            }, children: raffle_announcement.fairDraw.heading }),
209            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-1 text-sm text-muted-foreground", style: {
210              whiteSpace: "pre-line"
211            }, children: raffle_announcement.fairDraw.body }),
212            /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { className: "mt-4 grid grid-cols-1 gap-3 md:grid-cols-2", children: raffle_announcement.fairDraw.rules.map((rule) => /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { className: "rounded-lg border border-border bg-card p-3", children: [
213              /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-semibold", style: {
214                whiteSpace: "pre-line"
215              }, children: rule.title }),
216              /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", style: {
217                whiteSpace: "pre-line"
218              }, children: rule.body })
219            ] }, rule.title)) }),
220            /* @__PURE__ */ jsxRuntimeExports.jsx("section", { "aria-labelledby": "raffle-privacy", className: "mt-5 rounded-lg border border-border bg-card p-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-3", children: [
221              /* @__PURE__ */ jsxRuntimeExports.jsx(Lock, { className: "mt-0.5 h-5 w-5 shrink-0 text-primary", "aria-hidden": "true" }),
222              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
223                /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { id: "raffle-privacy", className: "text-sm font-semibold", style: {
224                  whiteSpace: "pre-line"
225                }, children: raffle_announcement.privacy.heading }),
226                /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-1 text-sm leading-relaxed text-muted-foreground", style: {
227                  whiteSpace: "pre-line"
228                }, children: raffle_announcement.privacy.body }),
229                /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-3 text-sm leading-relaxed text-muted-foreground", style: {
230                  whiteSpace: "pre-line"
231                }, children: raffle_announcement.privacy.decline })
232              ] })
233            ] }) }),
234            /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "mt-4 text-sm font-semibold", style: {
235              whiteSpace: "pre-line"
236            }, children: raffle_announcement.feedback.heading }),
237            /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "mt-1 text-sm text-muted-foreground", children: [
238              /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { style: {
239                whiteSpace: "pre-line"
240              }, children: [
241                raffle_announcement.feedback.body,
242                " "
243              ] }),
244              /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "/contact?topic=merch-feedback", className: "font-medium text-primary underline underline-offset-2 hover:no-underline", children: "Share private feedback" }),
245              /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "." })
246            ] })
247          ] })
248        ] })
249      ] }),
250      loggedIn && /* @__PURE__ */ jsxRuntimeExports.jsx("section", { "aria-labelledby": "winner-options", className: "mb-8 rounded-xl border border-border bg-card p-5", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-3", children: [
251        /* @__PURE__ */ jsxRuntimeExports.jsx(Lock, { className: "mt-0.5 h-5 w-5 shrink-0 text-primary", "aria-hidden": "true" }),
252        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 flex-1", children: [
253          /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { id: "winner-options", className: "text-lg font-bold", style: {
254            whiteSpace: "pre-line"
255          }, children: raffle_winner_controls.winnerCenter.heading }),
256          /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-1 text-sm leading-relaxed text-muted-foreground", style: {
257            whiteSpace: "pre-line"
258          }, children: raffle_winner_controls.winnerCenter.intro }),
259          winnerChoiceError && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-3 text-sm text-destructive", children: winnerChoiceError }),
260          winnerRecords.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-4 text-sm text-muted-foreground", style: {
261            whiteSpace: "pre-line"
262          }, children: raffle_winner_controls.winnerCenter.noWins }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-4 grid grid-cols-1 gap-3", children: winnerRecords.map((record) => /* @__PURE__ */ jsxRuntimeExports.jsxs("article", { className: "rounded-lg border border-border p-4", children: [
263            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "font-semibold", children: record.raffle_title }),
264            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: record.prize }),
265            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-3 text-sm text-muted-foreground", children: record.public_identity_consent === "approved" ? raffle_winner_controls.winnerCenter.approvedStatus : raffle_winner_controls.winnerCenter.anonymousStatus }),
266            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-3 flex flex-wrap gap-2", children: [
267              /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", onClick: () => saveWinnerPrivacy(record.raffle_id, "anonymous"), disabled: savingWinnerId === record.raffle_id, className: "rounded-md border border-border px-3 py-2 text-sm font-medium text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-60", children: savingWinnerId === record.raffle_id ? raffle_winner_controls.winnerCenter.saving : raffle_winner_controls.winnerCenter.anonymous }),
268              /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", onClick: () => saveWinnerPrivacy(record.raffle_id, "approved"), disabled: savingWinnerId === record.raffle_id, className: "rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-60", children: savingWinnerId === record.raffle_id ? raffle_winner_controls.winnerCenter.saving : raffle_winner_controls.winnerCenter.approved })
269            ] })
270          ] }, record.raffle_id)) }),
271          /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-4 text-xs leading-relaxed text-muted-foreground", style: {
272            whiteSpace: "pre-line"
273          }, children: raffle_winner_controls.winnerCenter.privateFulfillment })
274        ] })
275      ] }) }),
276      loggedIn && isStaff && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-3 bg-muted rounded-lg px-4 py-3 mb-8 text-sm border border-border", children: [
277        /* @__PURE__ */ jsxRuntimeExports.jsx(Lock, { className: "h-4 w-4 mt-0.5 text-muted-foreground shrink-0" }),
278        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
279          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium text-foreground", children: "Staff are not eligible to enter." }),
280          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground", children: " Admins, moderators, and the owner are excluded from all draws to avoid any conflict of interest." })
281        ] })
282      ] }),
283      loggedIn && !isStaff && optedOut && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-3 bg-muted rounded-lg px-4 py-3 mb-8 text-sm border border-border", children: [
284        /* @__PURE__ */ jsxRuntimeExports.jsx(UserX, { className: "h-4 w-4 mt-0.5 text-muted-foreground shrink-0" }),
285        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
286          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium text-foreground", children: "You're opted out of lotteries." }),
287          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground", children: " You won't be entered in any draws. To re-enter, go to your " }),
288          /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "/profile", className: "underline text-primary hover:no-underline", children: "Profile → Notifications" }),
289          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground", children: " and turn on lottery entries." })
290        ] })
291      ] }),
292      loggedIn && !isStaff && !optedOut && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-3 bg-green-500/10 border border-green-500/30 rounded-lg px-4 py-3 mb-8 text-sm", children: [
293        /* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheckBig, { className: "h-4 w-4 mt-0.5 text-green-500 shrink-0" }),
294        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
295          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium text-green-700 dark:text-green-400", children: "You're automatically entered in all open draws." }),
296          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground", children: [
297            " If you win, you may accept or decline the prize. Only members who choose delivery receive a secure link to submit shipping details.",
298            " ",
299            "To opt out, visit ",
300            /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "/profile", className: "underline text-primary hover:no-underline", children: "Profile → Notifications" }),
301            "."
302          ] })
303        ] })
304      ] }),
305      !loggedIn && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-3 bg-muted border border-border rounded-lg px-4 py-3 mb-8 text-sm", children: [
306        /* @__PURE__ */ jsxRuntimeExports.jsx(Ticket, { className: "h-4 w-4 mt-0.5 text-primary shrink-0" }),
307        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
308          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium text-foreground", children: "Members are entered automatically." }),
309          /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-muted-foreground", children: [
310            " ",
311            /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "/#auth", className: "underline text-primary hover:no-underline", children: "Sign in" }),
312            " or ",
313            /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "/#auth", className: "underline text-primary hover:no-underline", children: "create an account" }),
314            " to be entered in every draw."
315          ] })
316        ] })
317      ] }),
318      loading ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-4", children: [1, 2].map((i) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-32 rounded-xl bg-muted animate-pulse" }, i)) }) : raffles.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center py-16 text-muted-foreground", children: [
319        /* @__PURE__ */ jsxRuntimeExports.jsx(Trophy, { className: "h-10 w-10 mx-auto mb-3 opacity-30" }),
320        /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "font-medium", children: "No active lotteries right now." }),
321        /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm mt-1", children: "Check back soon — prizes are coming." })
322      ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-4", children: raffles.map((r) => {
323        const st = STATUS_LABELS[r.status] ?? STATUS_LABELS.draft;
324        const entered = r.my_ticket != null;
325        return /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { className: `overflow-hidden transition-all ${entered ? "border-primary/40" : ""}`, children: [
326          r.image_url && /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: r.image_url, alt: r.title, className: "w-full h-40 object-cover" }),
327          /* @__PURE__ */ jsxRuntimeExports.jsx(CardHeader, { className: "pb-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
328            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
329              /* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { className: "text-lg", children: r.title }),
330              /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-primary font-semibold mt-0.5", children: r.prize })
331            ] }),
332            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 shrink-0 flex-wrap justify-end", children: [
333              (() => {
334                const tier = getTier(r.prize_tier);
335                const cfg = TIER_CONFIG[tier];
336                return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: `inline-flex items-center gap-1 text-xs font-bold px-2 py-0.5 rounded-full ${cfg.badgeClass}`, children: [
337                  cfg.emoji,
338                  " ",
339                  cfg.label
340                ] });
341              })(),
342              /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { className: `${st.color}`, children: st.label })
343            ] })
344          ] }) }),
345          /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "space-y-3", children: [
346            r.description && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-muted-foreground", children: r.description }),
347            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-4 text-sm text-muted-foreground", children: [
348              /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1", children: [
349                /* @__PURE__ */ jsxRuntimeExports.jsx(Ticket, { className: "h-3.5 w-3.5" }),
350                r.entry_count,
351                " ",
352                r.entry_count === 1 ? "member entered" : "members entered",
353                r.max_entries ? ` / ${r.max_entries} max` : ""
354              ] }),
355              r.draw_at && r.status !== "drawn" && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
356                "Draw: ",
357                new Date(r.draw_at).toLocaleDateString()
358              ] }),
359              r.drawn_at && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
360                "Drawn: ",
361                new Date(r.drawn_at).toLocaleDateString()
362              ] })
363            ] }),
364            entered && r.status === "open" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-sm text-green-700 dark:text-green-400 font-medium", children: [
365              /* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheckBig, { className: "h-4 w-4" }),
366              "You're entered — Member #",
367              r.my_ticket
368            ] }),
369            r.status === "drawn" && entered && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-primary/10 border border-primary/30 rounded-lg px-4 py-3 text-sm font-medium text-primary flex items-center gap-2", children: [
370              /* @__PURE__ */ jsxRuntimeExports.jsx(Trophy, { className: "h-4 w-4" }),
371              "Member #",
372              r.my_ticket,
373              " was in this draw."
374            ] })
375          ] })
376        ] }, r.id);
377      }) }),
378      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-14", children: [
379        /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { onClick: () => setShowHallOfFame((v) => !v), className: "w-full flex items-center justify-between gap-3 group", children: [
380          /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
381            /* @__PURE__ */ jsxRuntimeExports.jsx(Medal, { className: "h-5 w-5 text-primary" }),
382            /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-lg font-bold tracking-tight", children: "Hall of Fame" }),
383            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-muted-foreground font-normal", children: "Past winners" })
384          ] }),
385          /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground group-hover:text-foreground transition-colors", children: showHallOfFame ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronUp, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "h-4 w-4" }) })
386        ] }),
387        showHallOfFame && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-4", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LotteryHallOfFame, {}) })
388      ] })
389    ] })
390  ] }) });
391}
392export {
393  RafflePage as default
394};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.