{"release_id":"01a1c502-4ad1-0000-ec62-adc54d3c69aa","chunk_id":"01a1c502-4be0-7103-ab0c-5ba4c75e1fd7","file":"BpTtuZlU.mjs","mappings":"+lBAAA,SAuBE,IAAAA,iBAAS,OAAO,EAKbC,EAAYC,EAAMC,EAACC,EAAO,IAAAC,EAAA,kBAAA,CAAA,CAAA,EAC1BC,EAAUJ,EAAO,EAAK,EACtBK,EAAUL,EAAO,EAAK,EACtBM,EAAQN,EAAO,EAAE,EAEN,eAAAO,GAAS,MACnBH,CAAO,EAAA,OACL,MAAAI,IAAeT,CAAS,EAE9BU,EAAAV,GAAaS,CAAY,EACzBC,EAAAL,EAAU,EAAI,EACdK,EAAAH,EAAQ,EAAE,EAEJ,MAAAI,EAAMF,iBACM,mBAAkBL,EAAA,YAAA,CAAA,kBAClB,mBAAkBA,EAAA,YAAA,CAAA,WAAyB,mBAAmBL,EAAM,CAAA,CAAA,GAElF,GAAA,OACGa,EAAG,MAAS,MAAMD,EAAG,CAAI,OAAQF,EAAe,SAAW,OAAM,MAClEG,EAAI,GAAI,GACZZ,EAAYS,MACN,MAAAI,EAAI,MAASD,EAAI,KAAI,EAAG,MAAK,KAAA,CAAA,EAAA,EACnCF,EAAAH,EAASM,EAA4B,OAASC,EAAE,QAAQ,EAAA,EAAA,QAEzD,OACMD,EAAI,MAAUD,EAAI,KAAI,IAI5BZ,EAAYa,EAAK,UAAS,EAAA,EACTT,EAAA,iBAAAS,EAAK,MAAM,EAK1B,CAAAJ,GACDI,EAAK,YACJd,EAAM,IAAK,iBAAmBA,MAAW,iBAE1CgB,EAAkB,CACjB,YAAWX,EAAA,aACX,OAAAL,EAAA,EAAA,CAGH,MAAQ,CACPW,EAAAV,EAAYS,EAAY,EAAA,IACxBF,EAAQO,EAAE,SAAS,EAAA,EAAA,CACpB,QAAC,CACAJ,EAAAL,EAAU,EAAK,CAChB,CACD,CAEM,MAAAW,EAAKC,EAAA,IAAAC,EACVb,CAAA,EACGa,EAAAlB,CAAA,EACCc,EAAE,YAAY,EACdA,EAAE,YAAY,EACfI,EAAAlB,CAAA,EACCkB,EAAAZ,CAAA,EACCQ,EAAE,UAAU,EACZA,EAAE,WAAW,EACdA,EAAE,QAAQ,CAAA,EAIf,IAAAK,EAAAC,EAAA,EAAAC,EAAAC,EAAAH,EAAA,EAAA,EAAAI,EAAAJ,CAAA,SAAAA,EAAA,SAAAD,EAKUb,CAAO,EALjBmB,EAAAL,EAAA,eAAAD,EAMclB,CAAS,CAAA,EANvByB,EAAAN,EAAA,EAAA;AAAA,IAQED,EAAAlB,CAAA,EACEkB,EAAAZ,CAAA,EACC,qDACA,+DACD,2DAA2D,EAAA,IAZ/Da,EAAA,QAAAD,EAaOX,CAAK,GAAI,MAAS,QAExBS,CAAK,CAAA,IAfNU,EAAA,QAAAP,EAESX,CAAM,iBAFfW,EAAA,IAAAT,EAGqBJ,EAAU,EAAI,CAAA,iBAHnCa,EAAA,IAAAT,EAIqBJ,EAAU,EAAK,CAAA,EAJpCqB,EAAAC,EAAAT,CAAA,KAFO","names":["source","following","$.state","$.proxy","untrack","$$props","pending","hovered","error","toggle","wasFollowing","$.set","url","res","body","t","trackRaterFollowed","label","$.derived","$.get","button","root","text","$.child","$.reset","$.set_attribute","$.set_class","$.delegated","$.append","$$anchor"],"sources":["../../../../../../src/lib/components/profile/FollowButton.svelte"],"sourcesContent":["<script lang=\"ts\">\n\timport { t } from '$lib/i18n';\n\timport { untrack } from 'svelte';\n\timport { trackRaterFollowed } from '$lib/analytics';\n\n\ttype Source = 'profile' | 'post_duel' | 'list' | 'other' | 'rater_profile' | 'post_session' | 'feed_recommended';\n\n\tinterface Props {\n\t\ttargetUserId: string;\n\t\tinitialIsFollowing: boolean;\n\t\tsource?: Source;\n\t\t/** Optional callback fired with the updated count after a successful toggle. */\n\t\toncountschange?: (counts: { followers: number; following: number }) => void;\n\t\t/** @deprecated RAT-327: the button now follows the active module\n\t\t *  accent (`--color-accent`) regardless of this prop. Kept in the\n\t\t *  signature so existing call sites still type-check; the value\n\t\t *  is ignored. */\n\t\taccent?: 'coral' | 'green';\n\t}\n\n\tlet {\n\t\ttargetUserId,\n\t\tinitialIsFollowing,\n\t\tsource = 'other',\n\t\toncountschange\n\t}: Props = $props();\n\n\t// Snapshot the initial follow state once — local toggles own the state from here.\n\tlet following = $state(untrack(() => initialIsFollowing));\n\tlet pending = $state(false);\n\tlet hovered = $state(false);\n\tlet error = $state('');\n\n\tasync function toggle() {\n\t\tif (pending) return;\n\t\tconst wasFollowing = following;\n\t\t// optimistic flip\n\t\tfollowing = !wasFollowing;\n\t\tpending = true;\n\t\terror = '';\n\n\t\tconst url = wasFollowing\n\t\t\t? `/api/follow/${encodeURIComponent(targetUserId)}`\n\t\t\t: `/api/follow/${encodeURIComponent(targetUserId)}?source=${encodeURIComponent(source)}`;\n\n\t\ttry {\n\t\t\tconst res = await fetch(url, { method: wasFollowing ? 'DELETE' : 'POST' });\n\t\t\tif (!res.ok) {\n\t\t\t\tfollowing = wasFollowing; // rollback\n\t\t\t\tconst body = await res.json().catch(() => ({}));\n\t\t\t\terror = (body as { error?: string }).error ?? t('failed');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst body = (await res.json()) as {\n\t\t\t\tfollowing: boolean;\n\t\t\t\tcounts: { followers: number; following: number };\n\t\t\t};\n\t\t\tfollowing = body.following;\n\t\t\toncountschange?.(body.counts);\n\t\t\t// RAT-182: rater-flow follow funnel. Only on the not-following → following\n\t\t\t// edge, only when source is rater-flow specific (rater_profile / post_session).\n\t\t\t// Generic profile follows already have trackProfileFollow elsewhere.\n\t\t\tif (\n\t\t\t\t!wasFollowing &&\n\t\t\t\tbody.following &&\n\t\t\t\t(source === 'rater_profile' || source === 'post_session')\n\t\t\t) {\n\t\t\t\ttrackRaterFollowed({\n\t\t\t\t\traterUserId: targetUserId,\n\t\t\t\t\tsource\n\t\t\t\t});\n\t\t\t}\n\t\t} catch {\n\t\t\tfollowing = wasFollowing;\n\t\t\terror = t('network');\n\t\t} finally {\n\t\t\tpending = false;\n\t\t}\n\t}\n\n\tconst label = $derived(\n\t\tpending\n\t\t\t? following\n\t\t\t\t? t('following…')\n\t\t\t\t: t('following…')\n\t\t\t: following\n\t\t\t\t? hovered\n\t\t\t\t\t? t('unfollow')\n\t\t\t\t\t: t('following')\n\t\t\t\t: t('follow')\n\t);\n</script>\n\n<button\n\ttype=\"button\"\n\tonclick={toggle}\n\tonmouseenter={() => (hovered = true)}\n\tonmouseleave={() => (hovered = false)}\n\tdisabled={pending}\n\taria-pressed={following}\n\tclass=\"cursor-pointer rounded-lg px-5 py-2 text-sm font-semibold transition-all disabled:cursor-wait disabled:opacity-70\n\t\t{following\n\t\t\t? hovered\n\t\t\t\t? 'border border-accent/40 bg-transparent text-accent'\n\t\t\t\t: 'border border-border bg-surface text-text hover:border-muted'\n\t\t\t: 'border border-accent bg-accent text-bg hover:bg-accent/85'}\"\n\ttitle={error || undefined}\n>\n\t{label}\n</button>\n"],"version":3}