From 42043957e0bf07edff261a54726c69e43a33ce78 Mon Sep 17 00:00:00 2001 From: Hank Date: Thu, 9 Jul 2026 16:42:35 +0000 Subject: [PATCH 01/22] Add bear + QR app icon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A green icon where a QR code's finder squares form a bear face — brown ears on top, cream snout in the center. Wired as the main icon, the Android adaptive icon (foreground + #0f1a12 background), and the web/PWA icons + favicon. Co-Authored-By: Claude Fable 5 --- app/app.json | 5 +++++ app/assets/adaptive-icon.png | Bin 3796 -> 172513 bytes app/assets/favicon.png | Bin 195 -> 4606 bytes app/assets/icon-192.png | Bin 773 -> 38556 bytes app/assets/icon-512.png | Bin 3796 -> 84762 bytes app/assets/icon.png | Bin 3796 -> 114235 bytes app/public/favicon.png | Bin 195 -> 4606 bytes app/public/icon-192.png | Bin 773 -> 38556 bytes app/public/icon-512.png | Bin 3796 -> 84762 bytes 9 files changed, 5 insertions(+) diff --git a/app/app.json b/app/app.json index 4e23192..143c506 100644 --- a/app/app.json +++ b/app/app.json @@ -7,9 +7,14 @@ "scheme": "campscan", "userInterfaceStyle": "automatic", "newArchEnabled": true, + "icon": "./assets/icon.png", "android": { "package": "top.mowden.campscan", "versionCode": 1, + "adaptiveIcon": { + "foregroundImage": "./assets/adaptive-icon.png", + "backgroundColor": "#0f1a12" + }, "permissions": [ "android.permission.CAMERA", "android.permission.VIBRATE" diff --git a/app/assets/adaptive-icon.png b/app/assets/adaptive-icon.png index 98b5fd6c54c382dbae6863ab0bc978dafa317695..5a37baacfc1e6f163f028dbc4dccce5309d47c2e 100644 GIT binary patch literal 172513 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�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 literal 3796 zcmdT`OGs2v82-+gqjPme=T1ou7I|%2v?v^*MGwoHjFm0ILfXzyEecw=Yl76nL}DaK ziy(+B46;pXEU{i9@OFgOOFQ2FCBcJc;hd@lW1ui1$5n$qk{;uyWgWqLtn7;jlC6l7UbP zmhe`=VEsN+J4u(tPq&n!EShAt5om_V9+e_2hus9Fm@U%Kgd6^8s0k*g!wQ*(nsKW} zo`JoQui-fC9|FuawENJ5L;~h{_zKZuB%Wy0t58Ra9wpw<3i;?W5|?3m;LB5Ds}>C< z#lplcd}!>{3(3_}LCpqJT+Y?pDYB(6wLuTFnoc40m%gJ)O*4v8qm3nU6N>Y{ z7JIG~R28zB_gt~T=IBBjs9?*~x`rax203Gt{z1JrY!l|Np!Z_kn*1efGB1I;@Tk^b-BvIAj2JdS`Eiv;!G54n|D9M+a8u93Pt;yUzA z6i;vNLo0c>&`atJsOPqT-H^)BUazmfIv_q$PO2qyisXNr^52;b^;0Adog?Kl6@Ecy zi8@*}1@2d7l~c16v@=rZOe>6xujB|cl>sdg0Xb335lx=OPsj^7SnNV{@*zQu6~OLD i5u$G!;|ynZzW##C!Qp{Z18*)-6;NBVKipj%jeiGrojw`> diff --git a/app/assets/favicon.png b/app/assets/favicon.png index 109b7634e4468733f200995f584418d58af63b5b..50934a4e14270a44876ee9acb36b9e0ed896e255 100644 GIT binary patch literal 4606 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 delta 168 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%0Dpl&@a#wDRn38C$F1aDisCsrl0-&a@{8!=@sK@ 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 diff --git a/app/assets/icon-512.png b/app/assets/icon-512.png index 98b5fd6c54c382dbae6863ab0bc978dafa317695..1b7b7b53cb4fc8051bfa1313a0015134c66d2635 100644 GIT binary patch literal 84762 zcmXV11ymbd(+(ay6u06I#oZkO6n7}@Rtm)-xE7b0Dc`0!XkIa)S zcOL`U)~=j1_2wFC{Vy%*S=)Sb3?Om}-ni^3$3NVzKfbRcBg1_7KD9LiEBek$fjr3- zj6y-tAvob2`IAQ1qUk1+^Xh3Qv*Bo_y3#N?^WX{#<9>l9_gTK z*khPrP>PIG_ntFF$e#SyE{Z+>W6z9WeD89)4vxua-Zryl7al}GtkrN>*K_P?K)<4B zw~*QA-n%Sq^rwXec08wb@4Sk3ZXzevJRO!oAwU%#!$c=AJ|z$y7y;}gstRlEl964b zprkatr4U2QQiDe$9-0E%L|O}zBM^hWlxQ7cv3MF73)z6pUSe>Ge-7!;k5HJ|;(!#X zQ~|Y5z?dNdyO52#Vye?-Y7DGuJvvaBEdvIYUKO51Gv$jBI-N%sMB_!TprR)T=%sld zTTkf3ND1YJf)=CiHEhlj7km{B@-t9D2XWC)>D|~;kl}+jYNqdO)YmO;anH^SHu%|2 za1lA-->b6K>Px|N{{~Xcm|!ga<5--4MBFPZgSw-W_ghsjTyrLlBXhG!bSn(IopziE zE%ev4`#UTwcBAQ@x6qydQA8AKSc>3MMBu18*!tyL$|Xi#hrW=*y5&A9<~Jbl8DUX} za3Neif;M9rD>Is;b<|1l%M#dR7$2D>7W>cJRBdn0d0(kk&>*@Vuwe6#ODuGa2x7=U z!Ar^k48Z_o37{ys{{+zmCd+T7Wp&7LtIKh*2}@>lPtn|fW zA=AA!umkdqjZO1MZ0u#KZdYOqn&0&aY4#pZKhoO_|G=R0DG~+|1&Cj#$v`P_p+pbD zvBdR)B*+WJJj;VY?)3Kv+1@v`<6=p;1mCUeiDGu`rM_;9nmgNyQ~K3UJu*l8wI)#p z;aL~uYx+Sc^pA5036j$QqtyiHK#(bkXHV@qSC+f8VK@`=+z4BQaw%;5Z;>GVm?bl1 z)E6)G8axRS`1{1pUb9+b*2fd*N>f@Qwdv{5vj<`-AivcD2w7Q#^_Go z*zYb0MMQrIj4{&^F``({Z}Ll~umIad-?|c*$S}S9+XqX^sf3_jkQy+cMB@|iLO-Ij z@TysfSDPhgZv}4h7xJlxq9YpP)q=@a9q-K2M!&A9N9w|)xw+1+nb==zvd~$KE8%#_ zX^Aluh5Y!4a#8j1;IPXDzq9vfihoPDzkvxrKy+Hw^C?dELLlJYDS(fJVk#Rp8o%n6 z3M&3SuAi2eF;Ma`o%xS9*W;Vp9?x6CjfMxFBf5}2E&m7zc_ikb(kF4oM-1pm;FrF^ ziiXuQ9sf`8@P~*&xHmKyiQJ|(ZIsTXhchKnbmm^78c!o;z704)&jawodDn1E!L5)k z;ZcxUcw*CxwQ`uWuWGs|l=JqI)aO7k0_eX&~OQ*{S>)h1#rf(S^s z3P4pMl|8MKl7De-^os?}%x6ccyp@we6o8DNTuxTM!f@w2rit$1v|!FRrUxI(Up75do5vH6gN9 z_iV$gC;?R+^lN1Q7)*nn?fogxs>=KyHSS0=x)8^gSOQvkRT0Uq0}H;_u*Hc=g{vo* z6lg-Ah9xDnQ-+6(GWBSSc@tyU;Ovz1GcLDWYoL)XNFQ- ziMc#tMAl96)-N%?1bK}5NYt@1nI!lSUy;gJVn2QDl=&2mx3%j8QhNPwt`m~vY>gE{ zjXGuV+AU-qM?TNe<$3; zu`tE@>(FaA&A~-n{IeSpU~Bg+Q&Tqgrbg^up>Gpp1rpyDYbe*deUv(l3)lhH`@k4$0j zmNKgyNzEvFy!Wl!R1%{#xyZOL`~98Z|HNs)iKZ)L1LY<^THj@5bd82H9a^C_umDQ^ z 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

ik4h_Kz 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 diff --git a/app/assets/icon.png b/app/assets/icon.png index 98b5fd6c54c382dbae6863ab0bc978dafa317695..ea11d0abf6bd76580e6537e0c762ee45debb7f4f 100644 GIT binary patch literal 114235 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%0As$V3w&m>DBssHnn@+CV^N< zOcege0}4yjWgvw@s60YJ(9T}KrT_^e98rReIG&ZW7x1Dpg#Z0`=oXC18rp3<_wjl= zGl<#SGN`f5P?j8olHyQIT5Ny`n>M~%F1rbc7iesYry)FVV_xv0eHitLmo+{+nO%T# z)QMEVTPB7=$(x;<(h~a+BCIP~SR#>O-*S36Bp}zYp9064uS>(*I~^z653$n0Q>B{B zW2$MsJ+;nk!n{0X;xUr1UL!%UNJSQMnD&$0*C0@)ojFgkfFbXooY%!Ly10GgSB}(I z&oM_jvy-^AKz4hENp<41=ES=kZtVks>#qPzNq!_l3iTW9LV7uK1 zm(6M8PQi0Izm`KvYTTe~ku5aLaaw%F$9}=DB_|kPRgC}lRk2T{-8Y_G zAEo1Du&xarucjI&1a%4$YFK))Min z>2i{lhqpT!9skY46^N1lSRqfZb^P?}#Snw; zeRJvB%U$!5`~>;>(4P(y@L?FeZoB z@Y-Pf8_>b9+r<&!x>xJ;I{_QvPW)e+cSOA*wcZ*G(aCl2+QSbu0*$(_+xC3i#0y&2 zFEAln`znWp{haM5eKi=op~%OqtSs(nj$66k3{YaG6}Hun$Eyt`z3Ib|ke`B-rYwYz zFi8Gr2@h)=&9?U+#*~oFa>fG7XPv)8SL<{Kobx`_s4>(oi-kM11wOF0y(uYzz#{Nc zABS#?e(@QzF+QH!#rFubEz%VvExyp^x%veXVQapM`#AO}wV$b66OXl*PadR;Ow!Tq zTPJ5{wu{e9)&h2P66SM?jA9KO+B?$9wrCIS3|G3*3lu972kET5lmPlU?`ha+Upp|I zF!kZKozEaukj|*_iZaA?%#t91yzL1m)zW#tg)b2brGMU61an)biyR)3Znlix_s+@6 z8ZGdOy7i}8q>V9+z2eVJgP|Qp>1I8y^YSEENcR zo;w%YKSUU*<@zV6ZQT+jzFvEEE`s&pz zqe(^|?p0wd12mwmz4V$r!W=Ur4h=GVfu^OnFn4Nf(J{|_(N&_w&Oqna2OXn zy>I#{;a)#hmJUiZ!p_DD%T0DM(*5KXFg2^J`&22A;z2wS09OeTb;TLq8n#{&XPf^+ zoSD9I?x`-THb4IlCDwqsro+=tnf=U zIlfRUdxwmeuSe^#7X+tPWO*7DSaBKe~etD$g>j8tn zUh6lCB$L`GdR=AMRFH?smYA}ZO=+5;j;VteV#zT#4HM|G9yl+ zTW+UmIk+0?%MqYS;pGazy4^oJ2|jE~xXeii#a#ud7T${dKB-6!bTimj1kA_a|GZvR zZE{Y%qmhTB#IJw$!yrahR?b=WZk*mq`Y(yc9~}Lm^)$L>(H7>78XV}hus)(y<_|RJ z$rFTC&^HQF!h|V0b1vH4jK%AuYe8XkfiC&_S8(RD6(BP}cQ~1jDogss5x@@W@uoc6 zE+1s8GN{nd)R();OR#7={1B^a93dkVC8)3=FWAFXJ7fwbQ{=7=d-3~7Yw?pe08-fRt7g8L>;SuAd0z0 zGP{Go?P~ za@qqDG&V6hvvc)JC`5Ei%;@*=#F+?-u*+8?uINrdpd~mGob;+Ly=@y5XFd6;`~^9b zH7qH5yQyxPzJxTs%sTFgG6+Z!5T&v%z1;(}?wm$F$?yg26ZE<_x5bo)2PA2uH^e&0 zxgiSAHOq2@sm9?}xuPV%QyKV!#j9w=|1@g|$SFW#(pmG9Me<|VhKy)|x|^tGNiqkr z(YRyZe%eG7bMuxC$4B~wxE@>5?B`B(x}Eh)k{E`9pAENr&n8*e1L@bjWOuz9g0BD* z!=SuUSJ_|bsB8|e|Ck~UzA0gxrLIj86umcZsvecS(XvG9ij+wbCDv3^hpy)V2_}f{ zH_u#wQ+qQi@51stgYoafsJuyl8WAS?8T8(+Odc4~>(S*U&Hv?4XxItr{fe+|Ga0h0 zF)O7qNT5)UNr!R+Tgq3Aqnqo_rq3|vpZyT~gAFz{O?%$$b-~fL7S>YaN(tO=WZ0w6 zDMtauTJV{ghZXm?>xv#FxlQz4m~Xav%?>5ewr&nTJD>7AlgV)w`Ll01m*1n& zoM)lG#J)mn#;SQc1wUBay(WvY7WD20C{u0%VS52X->!X}yi9lCxj&3{kgS6(ZMWx{6?JeH{>8kUmA zd;9xumsNRy`yGDTFd%yR`*~|&q%!Yh7+Cp(8 zKy1v7>Qb$DJuA28`%XM(q{8JN(y$!A-U5_RrRfy?$x#J*Yt?Ly6--?+`gsPTlo^K{ zY5$@2_i=6j3g7H_2Z?XI~M zh-2Paegy$mL~?|ZatM`Tm~;u%s3qx8F26x#~}8Wg(cn9DkLVt}L;~+Ryqm z^Sh{)fjJw>XQGMzV*P+AImSRP8UC!d3{OUw;S-i2cE2$Gm?51ML+O8@h5=dS<43OP z4Rgz%L^y9?%zqU*-t33%XwenG02rb0PZ7Hw>JPL(I!^1|l@vO`TYx$Fds+1ac%J&- z?vwx7_VMyGA9#FN@_+_J8nPA7d^25sZW(YEi7{zg(cYzobq}?S6XMH|mOk^&3T?QIxT`L|25GuX)H0%bgYVTWGNA zS65Haqug?HFqtr=l=gtxrKs-8DLIz_WaHzoYY(V^aR6*;mqkN4e*XBmi~dzsLJ;{p zQD5tv&q%4LajuFoQ2g1~+v{s{*jn-B;lBLU*vpNqW10bQHx?W~vzh)L_2jJYhuL7o zhrY{Gi3oE~Pia6xX)`pei#>1V&d02ELzGl0SDDkpm3se~0NJH}T=sWzyHKLh``h0s zb(%8ZQ;NXM?)F)w-~IujBnQi~>J&u?edc1fc^=%52p91u_dL!0AGM?dk*bk94qqJa zKJ2FBM2)h*1?=&w8@SM}=^p2FidKOByWMF1bN1?%neFA4_96K=*bsr{4kZ}I z{8kF5HjkHlaId7EeqoRkh(*Qjuf>>vwGD@?r3&#UNQ6}q4-NXTjn5AZQ z3vou9HMV(G{voGL*|=l>)DjW;#s2!Uf;smevrlus-kDUSeMkG$)pzp^2cF~cO6Mz} zZ5a`M(ZQ!XG)8tAYXD?a_|(AM5-*{|YiiQ&_mkD!6-p61(xjU5a>qv@19 zfliR96xB1x(9OSFQ}c9hNk@V3f$U``%B(+8mz^jZPY?cfqKrF9_7L@Zu{2QBfH$d} z_FW62()ImO^k+CL*&MvPyBlxpFuyf@WMp9Kj!`OHtG?3acrTYym}^J}?CB9nnseWB zBLegXS9IPz<$D&7VE}rIweb(862$pLUK;;Q+TaNA!R2bS{9_$2Q{zauQn)_Kx&OE` zZtT`Z9B*=%H2%Dld5GncsGB;_ey=&({=CQRqBWcPhP*K!gZmRJ(r>VyfBGNA&+dgY znK%F~i~8+7W(4j9f27OhqZDXR9e8X>i7)ZA`3`(Ux}>lr5vEkMs+P=a#GXWbn9An}!g zHiP2{Q7uoBmZneZwyKRPf%3zFJI0ezFxU0*8-|~A>VolfAmt~d z9_|Nf8H0u;YNBHtz^1;7P=+Ye677}^7rz+gEjE6{MC~H@I0M2-cYJpsXZ$rO?OXP{ zk))X#GBLeN5x8Kb^z8q1W%`=fJ;>)f?)ET+Wtj(ZxaKm@mORcsj+72TrxHBu3;CT6 zL`1SmUt2(+Eb|k8jvUbZQ9(431yWb7q({+eucf$0looVlA`TZ<&&_uObC=v7QB~;m zlVkrqT`rW8PDPMXpuRoUCVM_RI^p@#&Im=Kf&y?hBM zt)7WKl1vK?OF$fbxt$%`Z6Q4QZ+EN59lbqKvc$^HfJ^kCv3-+4=(6us{Q7UrwD^b+ zAy0FlL*|}AO3iH-+O9AKdK?Vs#s;YPi91!j#o-sS!x&8g6 zCQ>Sgp=BfJKdAjzIOEdraNmh{*~OkiOxpudzD4Ixs-V1_x4r5i({R-#%_VLIz&kUi(S4X%>+UruqdFsyPlNW`@mDy0LuI4|q_phT@j*dN{}s`HEp?lVki}dx%Xs!E$Xxk8 z#5lR6N3@6!7#`kI63*qVuv#6QWu*!%-RXZXot5pabS9E^gf|^HJS>FhXNQ8bZm#xc ziM1eeK|fn=PL?1Y`>_X@%lBhwbJWO6!Wf9sA(1QXJu>!Hf9{Oe+4=gKl9uFIN(x~f z*FVf3H+AY=yQJlYBbm`Sq!cxj?Sh34LkpNw9aM;X6+<~J;wQ5vpQckco8}M&bn*1m z7~4{O&<_~PkXBK^AO5*bIhg-jGBdjCIj5)jlg~i!0YQ4@Js&@7>s5dt+r{##6uHFw zKk1i~V&zu)(7B!p-^u{F!R1L`G;}IJ9lu{9XSak zIZ$ADr2D`pB?M!x*YBXNT4jg5N~*g%t#7H!_R;(okQieLoaA5UnK>U0I;uf1y~@8@ znhdZ0x3gyx`H!=gY}VKAeUK-wTXjAuA+}o1*ZKg^f6~-6-IRZv z!+#mF$^!ArmHMx(U}gPRo;3yOq#_l3oLz<$5UR)C3gbfxq!wyi=x4t#EVmk4fAJNb z`PHF9gemdYKs+qon1And2yX{4k$NbhuuotZaFIy_G9-ClLe zw1($gWz{Y)QPffx(qS=u?QU8j+ep{v>8Q8^F0SWwawEK{nwl%V>>u*(yrjmwc}UlmSgf9bGx`Dl1c zAX6j(=l~eezb{ziYa-A#2>Oh%JC7DY4u$fxj0&hh9|#c7@KNGhvASUQ2vR7{n7^vS z7M+tz^`^IzN53(|vp9|2^zz}mmlLmY8{Gdi05iYRM?fM=w){>ji7^ zP30id`w*ZvB&N|0em@j>1wsV*b$Fa#h4IvGBE|d2bMv5kVgs0*rZ-uXZrg%iY6@k1 zMuiRW{~i3_=l`>?#x=h^wO?ey<{RLkrkgNAP!)n7m;8J=-$?h^S%sCAD-Z^`URhCB z6RXnGE9~|#?&2h0F^-|uFBw(%bgm2eYVkJq|O^X($8quf95c{C6cLEG4$kUx}|A|uX z|EeK^3qz&_6t__#NXExnX-@TaGZ@moJXtI{9V;gp#xN{WYLY^oH7al5vt;}t;DfoQ z#pH}o$*5tLmmcfK`ogx4naJ+J5OEY3#hc*BJ2SgeUa50CPX)ncwzVn3TD^=1o)JV8 zko4QP4^LfHM#)JRSR{g2zQguZ0=WiJ*=5p%w1_C$!ML%ozbZp>sgF6wmwRQp_EMyE zu=!GW6U`~*nZF*r13+sctr8kKK6;-1SvIJ|JdQ2XyCbp-jEHo}#-HrFv0rCZ~d{aU17&Ey8xly4ULXA4)gAAeHqf8z<>Zg)( z$+d@Y5kbV>As-g}c>ZNHqaBtj9x;}J>?^S*#G(SDMgC9cK1pA$Vyl{P`V}S<8uARe zc2&}AUHWLy>$D%=f-T1;NuG4QfnP_wP_O-!LLsEE_4AgWpsl4U-a?UL@2gi|X3{c2^|mpnCi9{Qa)8}=oz62;2jvCs~iR8q`PxZ2OE#8`EByU;4I9Y&@( zTi>!rdJXi00I-6l=~j??PSe&iNA%eK+nQ|Fg(%&`m=`yTJccE>h z8(M7?7z8&Pa|-YNLw^*1pxXW+aYl(D_pMCu(`diO7piiIzCDxat` zpu8TvF2CW-sB&^OBF7_}uT6WA7&O*HSO}9GcxlYjuMmTBSkyqT$wc=A#{S03bX(WEO)9e+~ zX(4!hVVaq8aS;nT7BgFpDqxkcKUq}5^JDL5C}dGR)Axz6dUL2Z3GT}Oelt$r{WN#f zM!ZpMHve-L+`aFY9~Vmo9P8mB$ESY#s!=!z8R+uN`vF}P-d7^U>}$)W8lIQQY#ohi z-Pi=0D4-UFM?@)GmD_idP3zA4SS6h8$W=H4c13K#Mro%Q&uiJ*PPdlzqY7YfH}UUc zif9n%Q!}vEAdqk~*s?6~s&CED5wzxJe;bA&BFb~~7E=oSB-;zmU*GR(HU9Yg1g4h< z;?o5biP)aJBakafVK;L>dHh~F9HM+I9+C5!7RhssVoAt-b+#i%bzy}l<7I?SO{jKG zu*XHGcPtmbnCcZpsO{@^5J>S2!Sdxym; z?tO3=`tu+h(9_2aK!4ovJ$L@Qd}phR25p==P@aOXK|TymQAp@BL3%v!CLMAiH?VLe zF#5h;2oid4?WXu@KATP&0kvEk_yH9C?l;zs5(E-s*PX4u0@CJv5`m%3T4_9%8E2~2 zAiJHt5CG2#yk70I>sBb?(-448ls8i$uPNj$4b50$^BuG7LmnJ*Mrf2-V?<**l|>RI z*F-JZ?<{XCi>Ix5N*!+Iwmj-=FhyEP8EDX!d&YV}6V8V$qL?J~MEP)?4YOtPPGcjs zmjmGbD?zG2+WhEL2}`>P4%aH(^X=P^uk)G{9HtWuO;MIi6~Z}s{yNVcZJJY})ILk4 zcJ`!-7D;0;8#kJt@PR3BzuYRWx}#d(^%W|ZFie-{GJ227Z1Gb|os?4n!Z%Or3Mm9J zI1wPFTLlM!2BOt%=g2{dXRqNExAV__e5dnEFsOR<&WZg`u*~!FUF;}4zaB*#;ixmQ z5!_>EXIE01c%TG$0&iPV9QYWhF_Scjx(u!=t^Kpmo+#C1wvOESA8wc5hrl)!Z z7i)vj9ggXPSqDnbwPr4bs|2J0gFv(Xjt$WUYWkCA&0vAdonzT_zSJTV#O#|>A00%0 zDq8s01IE*1L_-)*NJoy?o^(61KH+CX9V6IBPa#z#XhEXX9l#fR9YjbEJgqK}wsb2^ zeDO8it-zc5^$06l94jjcg=Su%>>uScO=<5t-m!$_RClec>|MskwEn903tAcq;8!nS zic*SK{`nsWG)xM3A^*Idun=4h)sz#bmy<+j%!ooE1M>}{QE`1yE*Y?Onmal^l=X6TA6ifM-Pwcvf}{ zSNxxFkA3-Bc_`nw*k%ZOKIIB*x&nkGeSvL9<-?*^!o&frPbj=0%3p9UZT1H0|DlH; zAviJhIkcAC`O$9v6runL4VJNXX4_1txeq_vQ?YFLa_KGs+wi~Kr9oKFP{0ENaufye? zl9zUdWmrgRIiS10wyKlk!Bpa)JoCU6xj!Fwi|Y46c~f85*)B{&bqTlxWA~VE-L+U0 z)k^U>_6Ve}$R7Dxf908A46@gLtLorqe$=YuGy-TZqXuKH$?jDa7)j~$h(!yCkx&hQ zL7*3~o4|LIS$ts$+PSxHT?kWUZht|Jd+>h7q~o@!=hx}hICj4Ps}t<|R`~_VzOdk} zi$y{KPfxFa<{ty|v-OPEZyR|7pJ!sp1QLQMUI1umXET?gSH_s2CVV@*1O;RK&04tJ+Bq40phKYSyFgiE+v}20H(r*+*kwG@Q zem@Y7hsSkVytJ#lQ~5L^xKS+-hdm2*Z`$H0=$9S~=hI3f*v^AjWmkMmGk4hfMer%8 zNeVdh;5bvX+2Q6Bu`vd#$;xpxGL1}nU~X`GCzK znJr*Q0Ih1m6WqbaejP9uRHd0;8NtPiSSY>M92VFbnFNXm$KR3@+W*1K0y@-W2U%11 z0G7m!ukFj9HC6Bbc7CEn2ObD05ul$w!gQoQu7AG!Kuh7+-ML*|%(>=!Il_Zj7Cl)k zQ5YVgD)i%zRYTtmBMH0Nz3$)xj|fvftOrwut7~vW$Y8#_YO%jlgrn8zN1e&>Ii~RT zzP~Eim%1DJh`56@@Ckyh1xK8PN#8%Z_O@W=%kwoG;bi&L$uja5{>d_h9gYo-} zg->N}1UL>lviq86a48R#KIf2KE0&^&yKVYYR3n$+`7K}pFbtf54CK|Z`Rr!H$3w$f z^6b`jqvg$MJUomjWTe3rWx@R7old|{E4ooBrEx#cjxs|+%|Lu4*fQaLmD>(To8!{D ze$+WfDYU}WEo2*4+Saz}9F>-{w7EGYg>}=E4QbkTLl+flccaYCM&_w;Ul^X5@M9aT zohVt2QRnotgMYnny#cUu>(};OR@L4b3{3W7GbWdf zI1QX%Mv%QnS-3)Y1{FUlwk9E+8yU5-p%80DW-=%`?TH{81M1=ERuihzq}~ySjZTM7 zGEm)nzcQj2Ecb<@#Y?&fMJvh@dTt~O)HU{RRvpe?o&7$Fp+%@c5R{R}XXo90)!U`Q z#uE%LkW9m*89uiHX_JbV^k}LMDPzz|p*8!I`-*aPNYFMB+c7OSpyLGCK|PU@Cz}D; zn?4cNVjneOUF~4;r2q*Gx`nPI)nn+Sca3WhjL7jO7Lw%oA~mr0t?cbb-}6V!+GeKp5*%Xqtqy&?RZo1%0~^8P!&)QeCWzw^C*36*3|*R$9O=9UB$DFjosZ@P#< z81rYXu%MB-&5d8dP7pSsX-XNEq##%esZ5GfGc%6x;^r|eAwznSwjuhlAj=tEX6y9e z*rlSEIYXu6ctccp=5&Tt-eaA2;h`#Nb3zan3>Npb-v(!pS!=qy_Uea0sdnU6M?^;m z_P6;7ngjqF2cqF)G!+GIx;wVN-j|g6joaCT}@iWo*ejsh@FaOjz zqbvlpNty7SsF0lHewo&Zw{I>(E8_%Ay_th_$?5yGs7Ky&8;!^%6#8q$AcK19+%p0R z$XEVf0;T5P(5Gw$z(#k-xcR_jebq}KLo7({ec(+DErj%1AdH^+JvAa{;Nsy3lWDCj zx^8XjUOC76u3t%9X@-&$Q***ZmPt{tyKh?Y?ps{O42TzjU0#P*t*8Vp!2ELSPCSHx zv;ePi>I=lxhHBqq)KpsEsmmALn+t}j1fb2Z3Ghtrr%Q_DkmDxdnD-RyRH_PID^gmX zgDKWgHvKS1s#k)m1EM1-p6;=r9}vJXeti`dx$ov;;&H4m;j@2rW`*5^RRM-AzTu@> zwIQHTx49%^uR?0#@h4sY6^&X=`l!yU;5#9xu2xrx@9O3+o0r3=l!Zm1UrhFuPo>Z2 zY)mLoV7trAE20BvQTxsc?S{zvWHZM@V_`4dx8Sp`Xx%kRp2fa+{@Ugv4ymDj;d_nUy76cDa0R`EnLxUB&G zy!{Y!85fv)-GhP2Nt7t21ayHrZKuibt-Djpi=v5YpQ}-}rv0jGe zqaS*GtgW z8!uv1d{W~XkhXpL$Z03hP5)H5ZjB1Rp;5QyGI+s6cR}$}oSwP`3@3!&pnLfE@O3l- zNgn`(d<$RwAZ`BbR*dzJ?7d2G1`4U@!YzqHEuE0O%5;-<+={YMa2tA-s!(u;h5DrD z+@eO|-7Cq|$DOa4KBoO7SxKYXUtqS@{A*mVOI`(mWI;e=)X%g75D|{H4bj4k-^USaeaqVEMdm_||&lK+ji`UNuisdTo!|B$aRPZ8F$Qfi1^PT@jK^N}`pSJR@^ zq4UNL(C~+YP{a8b6ZXG@Z|n^cDjfO0_1!*mKkROMN^n1l>;~VVB?&^QVmq~Kk#-jL zOAOfaoRsE4w44Au_UFyTZSjllWuNNGB5h~i!=G8|LKn465{zN424+{FjHE}f_Mj}P z0?9n3X|Es=)?dmK+GZcq#ztE6i9j^|0P;{rfHvM|JN$teg+3A6&d;wfSG)^Bd~4`1 z(YJWxl~>_UiwY~+WK<>M3M5M-auQ{WAiQ=zS!bO*qy(CIT!G-^f7)mPJ0c% z+v8s3&Ea{vusyq@hA?cVt5z2Iy^A?Lx9O8rfw~OxGBJf6%yufKz?Vd+B6T8)qf4pt zdrUk@v}z(E=l^Gw$^S-&?f&!u@CvEQ9pVmtk^uj+$4S>y-S=AF$iMpLcc!2;{@}xT z`UWY~ZNDA*eOM=_@%%T#UAhP|oH1#jwmm0?mi(kAdQKvN@>jvn)yS!_`h(yCKcFp? z-u3${hj`~m6k<*E8W8&Ba9o}RAaG){ub)u-GD0j^DY%^DH1y)|{89|NK<1;N*Lc56vVF{4)RZ)sX0_TID~Pa6F$;<6l?QoELJ zKwS5Ekc{$MH^M2@rIlg`I_B#`8B`6?d%vZwvd=kw8@2pc`fN-6CYTajbIZj0ettX7 za+}-Uin3qZ>92h>xb(BwKVj3c$3Ex$#&rOL(hFQa>;izvjs3xy7N3!<|FA2+4)O4o z(WxKuEzre7eYDaFT%FGCD@n;oWH4B|66LYwRSxxlkg?$av@_^Uk(KG&e!I#s2VHRhSKuC_WOTP z0eWJn$h#wD(!mnGJu* zGYbPOamW80*|+~5+1g0a&aWr8lhvQU(rJDqMGi%NyRA?^eYC*NTqNwXwWb3qN>~D z>dv36i`0?!$BP0Et=rr?H=iIom;XGF0b=7hKx}{#b}03@(Wg!Qeq|10r^>g|)=sJn zq@sqe+xh&e?vQtDUOsF7ghl=9y#+)gGLlp$-j^vO~LORp%TBV4rXCw8G7L4)k*+|-)NfDy0?IRrtQr6yUL@IJKC0v;Lo2Bre$3e<^R z3*x20MFRky{^};s1KY?YFGkS>*t(%GF5i z=X*wx5%3N>G_a3*aDAmFD-!{R<~o}g)mXeU|2;iF_=1m~>^_7J@%^PKggcP0oK1vr zhX9AghQV3(fcg)&j+jG*vQ2->ahHymINN&xz5$_?MkLjTl$(+NA4B!=E^~J#YIjPe zu>MzGhBS4hc8Q@NecgDmfT|(?il}&w zhCoKbks)@!<%ekz>ytA!;FJ8K`r{oNKT0C+IDK#L(aEQS&siSa67AIcICMyTQ(XNy z%d_i3@$GmDBvlIjaaZ#5z8B^ZOS@x`t3JO6-YBGWGpY|8y8fKU4mt4Ah6h#ARvX_% zE=oqBLWVrGNCL4$3u)J`xXIR?;0)&YCS75_CB%AL#hU6Z6WCa_eY}D^Ke3zg{N?AG z0%58@Qolf=2VW+r5i+13bG{2v%~G5!qnN)z+{$L0i^FjV6G}XIC)tZT=CZk;7 z`_K0rmzzWz3M%16Q{j zZY@JxlT5c|=81;)?nAF~STc*Rt1w2I+p|&|)f@qDLibINu&BhIiSytO-S>PWa>Q=l z*qW8IZ+^$i=6L#@m!l&^uzy`ulYs8wh0-|^3gJd$>C;&sH*KxG%?_)m_ra%{&HUj- z{>cy+Cxr|p8jB?IGC%?Y2sqjep>5!2IOexnr5zM27xX*|e6O$%){UJ!t>$36`_$o`2zKb?~K)|szO_4JZI(d*^bhh%={(SNB@92gf z|D>zzJ2V4vfP4fk4jWs+qyJ(XuBjYmWUT-Iw#a*_R2IZwuKX89*DV>!%kLy+c>whl z&95)Mwozydr@%A5JEkDgzDWsdP>gJ(ypE>lVk1AIH1V=AIIP#Iulm`^bTK%}x{VLY zBH$TsChll8+B<4^)?>dYsWB53feQ$4Sc(4u$^ZsBK4K6paP|mVZ8Ki0E|LB& zWIHyir` zJZkI_^Kb996R-;PLeR0J?RF+S;zs73JUV2Mydp9L!57ngErRLBX-T-e$LYH=g}bo( z&r7SKYR_?he3AE?wswyr^rWXoXBwYx#6>2%t$Q!{g||KRlV#ersY%m8fYHc$w>=}O z-gYn-4h9K)f{R{|MCHA#cukfxI0j^vUmeX>80%-sPmOdiS2-kKAvSBk78R1yq}IZw$n19d`;Dr)4}qITSz~ zAp7Zb-<&k9m_2OyTK87N|G)bgO2Bg?^H(u^hHU5dz9L%EBc42mo@u5jlHdg; zAc<*ITc-w3KbT6nuWB!4v|rxp9=j8`R8J8&7Goh`R|Aot5 zLNLkKPbdT8jUi<>coTSv4s&<|FdWR$eo*@?7YaW<|9B&-iCnF{#&%I+)Y3sE} zqoq(gzv1S3^-5NjRp1i{OZ8l%Fc^)1EvIYq@nfQl#camXIOH}HJhm>z&qTj_m%PwL zt_f2pl0pLE@9FP17_i)A%N!XH11h^vPAp$L=l&0{+tm~@5wrf>4icl^2MhW`m96xi z&!$wH`%TPi9w&RzBG@(q&*nXxmL6m3l1=UcK*GO#dh}Z2BZx8|ixDil_2(E^bRpw= zadABtn3DKS8fGIFI?{?}`(i#nP3+29>#!L>W=#o(sOHj^7FGH+^U9yrt~H)~+aG6l z{M}J@jNp&w4IDAwGJ`Hk%7VAAUOC@qH9I@?n5)|^-J01i3&tew7tZkPp zbZcxP9Ql6JV7zTiCl5BZfU<7O##h5{4Y+j^Y$B#K9bRa|wgg|DbUh}8Ma-R3{Zt%t@K+UzQ{H=dWfTFD+dcNOnxqt`E1%yp%Mf zMF|Kd0$!%@!06$8snDOJyO?&q)hjuh1IQLrK&^8Z7!7f6h?bzt2(#J6c;{xs2>;6P z{4&(NHV^0jHwEFa3jQPl-X7{KzJBPp8=iW+?ifDXXlBIuK_jztzuJoup+@#6_F`JgwMUMY z3yZY8Qy`=iiy}4us&3V`SnK%H{#MChjG_QNHDX9$4#lMI!`m-)FR)4{XHtc0>k1Xf zUCqQ(|4H6m((i}b$*-Eem2vq4n=@Y}7;NAt{D$dawl>XM$0m}+XK20;&NkmGe*DZ) zQgA%B)RZke`_Z6RBk?XBJ7&8z=jbkYy>DqpV%oEx>#h9ZTR+!(T+J`UD9bL;8Q7oc zVwUt9(-ltL72`6KG{AUuqa?jG?d^?`_n`&lkz8rqEtKZmPCi4(p$WXz5lGo3PVS8W1}Q41nKXy_|6}BWD$ckRKkrF3%$ZAK08eEey_Ock=#Qr z(u~^tXO=*z?A}GHT7#0&1%(PtlQJ5sSVRMQEuAU<0SaVpu$Z9FI@P~z;g^`?ecJy7 z_rHwFDg^@J_SNxcRFtQdyW?|5`DW9*KqIwODbcR#A8a+}jJo`lA*!vYt~L7_w5`f9MsC?*4BLu+!_=XM% zYp<6(1MtyzbG{dO_I`i%UJRu6GODe>a%+^KIP9c-V_feCnZDYi+VMGO;dV)SGAZid zXAO3I1u?VsjlY*}1E2i@K0C@EdQ-60_XS0YRtNX*4IHHwN}nkstvF*x*PJ(j{0J-Z zD()u2Y4ulL`qv+oQ-RTX`uaKJ;_ewg=nsqD|5&YE$x7?~f=e11@5it6q)I~=w$IA4 z&CnzHEI&hEJDG!}mrqZUefPu76q0(E4yS}yCE2Wf>slP$x#?L_$gB3!`+Gj@hMu2e zv&uY$3Uv~!)O~iRhoAc$&Do#yW(eDP+@56kP-7{t?!w#HAu~FrGVb(-IP1nf>qGzC zEA11d;l|sm*A2dFJ~PVmupv~PaAbqZ{mzHt$m8_eFofcK`sG*h_R(y`%@uU*akl#V zoYB!gw=UML6^=3*&t~=Kx~`Jv$(5^x~s^Rel#aD(=vH z)>HX&9$#DQx>956Vu^r01Gg8tUHmyJ%Ww6}N!Q4FAbuH9p8Yxh*f1O0|2a=Bjh%hr z6V;*ot46r!&eT1QLgTyES&hQO7tOa$w|DG&FOK{Gd2pbOEAgk;AI4vw&fgYp^j)ep z^YZPDJKW&VM>RKHe4Uq+r6&_nZSdZYoNJt4CWS`h04c z-(2;&X|^;tc*<$*);ZV6$mu}WoI$pBdARB^$DPWR*$u`4#Qc^hH{0v z*ykPCc%KFt$a-H)*r0D>3|5Aw_f$8syXrRwDJeX!k0rI=Q6|&&RX9Mg_pnEwwIM-W(>8 z=S=l}4jP1Me$-w?rtvdv*nT4T%L6!2v>Wof{JCR>v>d+c7rpCvU7jBoRw2hVRPm}e zZ_#azF4V(8+7l=4(03;f5-L=+Iy5`W-n*X@LCeV&DqrupxMOyaDK+qwIDUbQy3AjP zg*v#~AP4Zpri0YD9 z<-L4~8-qb%4A$r1du3^Y#1Y`M5E%E3*|U3z-y;+JVXC?iY3h};i`Q@w9?w*&(5#Z# zhF|b|ef4V(b-q+< zZ&GV+@;NursY3}Mh%kur%!T-w(*h3Fr-Q|GEPrBv7^MNx%dr3!$7V!33%;9e^Ewa7 zd_$T{Z{kN(e<6(yTLKxAs#*=$7fu#$OmCe}xGHlqT`I z^x5~klg<{LHvrGhIBNoOvR?(rgdgFAVBN;MX*Qe^q( zWb_w*nea!fr3+ArfwV7Epz4Uw>ZJ22*$Zb}Z&#kOS=j;o^C~t5mH$C&at^+WKZ3OJ z4JRx`$R`EBA0nluJ1xub6R+vs_rR2zwXJSiioF{u0z2AOvH@{5c)|Hrs}u8=t%f6H ziQ>)ckz^3nGJo0@fLGe7djU}na(f4-4n$;`$5q_>yeEXD8G}*s;J`SFwR3%HKRN&r z&~IqE(lAw6vn|>o$R|0}n??{rxtxxZBEOuY8nwfXF zz!xbYrJ72BZH7K}nWjT_LQATy>l;%4I``W6NanJ`IHNMEIV*rEG1&{uG6(%&2Xxq; zuPx2OZQPMpQ0B4>fhqM#QiFL+Bluc3zwG(1)jP>%o}T+%zatV~eAC;iA_sb+|BHUK zo1GubT8Pkv-*Mb@cdJW(s{Vlc=irO=>HZX{BA?k5LQBS%;n9bC9c9h+Ef&+5ZYFqP z3ycp^vG5|o#Cw&D=|jy#_L@h&;f2u|WlMF4a)41q{pH~_{w23$xkpTS*icLBRp-xR zh3bv9L?C(mPI20zqQc`p-%d9CLR1j=b%DhLU|#nfc48cuKp-rTJHGvTNHDwo%Y(l9 zA3M9kRy!R-uFt>F1pm!V_dUGfcDj>I?S^FKkI#5b7l&jCGUr@4jubZa>!1So91JJj zyp9LY|K>Qp&wrcbR)qoX(0lh|h}Phdc$GmyN-dwxemL03yh;vhsKP3+w`OnVxT>>T z>xqv=D0$s>i9(U1)7REN3w!%?S4eQa1FauDs?9CBxMqHmi0Z!>i1X(Jt*lUv~PAq)M66~4PCY9ntnvY@zJi>J-g z#9A|z@BdAGGJIZHL`4dTCy()F5;FT5Lf#r6hT}HiQ$1a}F>d_jr8$1{ysFSjH*4!H zkaR`LOnp_TZm%)b69{;9!JZfU>bb>J6~|#_-u8W;-{Mf;q49*jSuz5B=NsdTOdET* zB*>ak{PA-(Mf9)lJMCO^1B62<^6b`q{~8P}>I*sVZPSXqoNJyU^@UIOgxO_6)A3enQ-VkDT z$JU_;*6B9CqY{w=t2(0R%Cvbb`%c>PfY-Es>j2;qCz92ebqfy7_|Nucr*6U_Ym19wTwdRkxpiV#ngSO!it z?7UgCGxb&4jYzaRc!UPhc-(+oqEQKx!#A7GZwptRnI3(la+?jHt=ai0kY|uHXj0`z zw*?iH)l&;46SCEOzrJDiYUGr0t^onHVBCP}#h4&SnJG^y?Yz#`cN=ooDABUzo-xDM z+h53jls}*FaGUltk+;`K^DLuBLZQ!WboYRK=l-MiNYa?6LQZWw2Gh_-nenSvOOV|y*KE8>j6GLObc?GKUbmT?@1Qz=l^x5OL7^U zR%GV9G&63(k1Jiz9mn6p-9UhkSNb_hY=hx^cRz|a2t6$s5bd{}t$TKln?B`LGVEyt z6gP9$xvceXBDH+$Va_BkC7m@T z8OVbX8^Higkd}3+Qk48(I7Fr@!V&z?MPTSB_2GRjq~BA9q2LNkbn~aJ+-#tvWrmp= zpLS%~br)KVXKL)Wc%|!nmIDanLn4sjr?As%Bk%RIgyUkO*;uOT{r8B&hW{T~*8xuT z+xL&XIm$S8hin;9q(X%C9^=Xu`u zx!$g>F6zqf{@v#u-|-nS?{&VJ-?`?#^`o*90x^YYiHQ@rlQkbAjNv*tp3VPFPN1qc zA|=HXLT{P;&`s4UN-ZX>i$u_@H@ss`jTU0Ma+#j_Nt0(yk=yi&r-vsGrj-FRj1)8) z^7fvYJm^Zo_6q*;NnFFecPMzi_%r!*%d^*7<)vV`JpkUlX%#{T_#O_&zq|1A(T)-8 zfiWmvoO*uARGavU9~U|P>`?$!fbU~2b>tTj(YeN{#jyNWRAB}|&Of)?gPAKdvsdve z7G`#jyrb7|vV7}1$ye{+t%9Yqp3$h?^I$sp{?QLo5B-FqxQG%XGGl>WZt{7He5GoC zY?{~`O(D>PeS0Q-w}MK-Z?@6%p4pVoD#(HBVp2SJdDn)67p-)D;N1iSKLy2epBd((e2OPz1Rkn!EwM zKGEvAt`vJo^%6i*r98ve-0M0K-Kf=@^*Yz@VkB~N^W98xYa;5m{5&b$ota~*$#Kwr zi;@J-RV9>w6z_)SxytFvtI_z37}Z=!=nHiINp==Bf%3;}UzGpev)f2m+oJnJ6r$U2is4 zNbeCNGwrVwtU*Zp1WE4iyVQGUV9YQc)lbLO?jfjG5=9ov%Oytj4s#0Q+_E_mv>`P9*3R_!W8^JCA9C{{P{)g(OhN>3QV%2euiApY zpgd%oO^S*pS~-66Vtp6n;o?xr${RF!p=uM2e>W!B0Qmw4WOrg7yjN7u z)e}39OjY*O?2OQ$q!*H;`FVWLXYYKtVl^`VqgOD7iO9#&{kr>_H5ykJOx;PKT#;VC zzWX;{He3zT7v_I`tNQOL2XZ0MHr8JH{YgyyZ))l)SCRmfw(NbBGwkQ6KE0px^SR6# zgL;%vcVj3!^m4_N@Q1y*Q~o5? zpp;OwtWf%WG%7kMYSLp6VHeEBF9Y`C(!0B>X|n^ZHk^gydsTL6}U zb*aA>jFOe?E7=OsNv@s}8FeO4WfW8a(C}F0Z~bDj%bWaMbj0Jdi65rM!nO?^sC;C6aliCdtD1k%-=R+Z2+kww|C6tyM5js0G1)z@4gX^> z?pWZpapnht#5gH_`A~42{mqYAu&DMT@n%VVtHhEOhDPyF`>Kck$_o$n07f}Y6O)4~ z@+HA#sBhbkZ*INomJgAj2y67+!R5nddNYq>urAmu^$*w{GKdIINir9U#rkX{1{uLB z*f7|>tmBfZlGSi4-AL#>uXWA z`sTb4@&~P_a_57kuIiuHedj~6&W=iJmD40JtzXu6eV8vPk=LgKm^T`hx9KxK8+O1X z_;cz^?%C^xYP#|B!O;M^d+ATPLiX3vg!tF<2qCIQ|75NhY*G2UZp(X|oXs*&%DB)Q z`WO~KaJn3478;b=C*wJHom$|)*I#+@WjYcDN5)w&yN1gkTc>%~VDNAa;(PidQkge+ zBF8FqH;57B%xM}ww$rX5aA#g(K`0?y2lJMPE~_B8r{FvN>xR!qda0;NVwa9j*B>kr z2Yv%bqj%FT7GeKX@eX;b<#q%Ur}uH538Nu*2CJR=eH;`glcW}~W+3fZb0#l2qM!G~ zxtQ+tGRsMQN|zMcc}~=O>LTL-Q#h3K2_dJe*X&*p&Vh- zdW3<{x5&8Ad`bJ(54F|K$6Sr6fjq>VTR%B>)JQ%-+5H^8=!wV`Z|#p)kAtgSDg@eS zsN}BZFEx4fH?=~cp6}E?o#(C_%~yhQk1bI~Qv}5NvS}7oo#epBb0OTUm&Fwx@4iZ zj)S=pKUm#f@Z&T`bHCEQx?S3pf2KtAI!YMlD;NA$S$_mV{bgb9t+HP^@r-YMpW@Ea zSGnQC=HyqjRv20iVZr{J6qgICrXB!Re&s=Y`^ClL$pto`zvr>VSZ@7dcFv^isS=x^ z>~nPnNQy)t3nb-E3YN*G+&t>meAdt;Q{>%OptrqO^E?!A%Q7X6tVU+K^J_M89~?## zYK68MNl(=5#9p*p`!&Y7Io3v@l^tCs9szOkJkZHAC)o~`=@ zmi333B&c#lCR@cv)eO>TL^o zjE#jizj7Ru`(3AU+M7zpvfB)_AA~#%Ss&FzfXoB68qLQ4TEZhs!-tvXFAT7U91uI3 z<;%^U%fPzkzw(;MH!n~$V~WlUPqth|WgRw)RIk5lwTv>TS^?iLbvLnC%)Br6DTqc6 zo?z3aUuzC+PQ5UJ`I10X38b1UjxT0$UOP|I0v;{L*P6-UaoR<`>u3o}jK%h_llaLy zw)g#-kBD@YaH8I2G{jVb0yz_{Sz3aKm!HHn$wXNpw}^ve#pm!TNB_w6nT_XR!ws1k zB3wqfFYRfiISNgIhg*p~SD~qU|!#sfn;Rh%umgvURaEsHxp zkF>guG9k(+FMjjrg-qcwvRa%-8+gJE`$a)Bp4nfF#6rz_BV8gl*U%;J2f=TPmZazs zNsP{ytDsPXYZ0AT58P+8Wizne4b&L)XBN3EhGdu$%43qF-}Ag%r6(Hnf-cRoXXbFITl?MNH! z@x{UjP;EQE(m%PsXp#I`KXo2VSQW_yND93MGOnUtKr4n$`&jj&IYweH&eFYhTsUMY ze;44VauP6C@5Xj`wA)Fi(YTMT{}RBt8GQ<4Ch&?vS?gCD1{GS|#Pr&BpJg=1Mqi!U z))7MKQ`s(s^7ATyDI#E_*1B)Onn}g4J{A^^ECAk2q~Mu%qJM^F*HZ!Qop}{ODB>#D zf>8laL#Fy19q#gnukS@47f*J~Kj{rMom9aZuNCn|>?I6e^)nVtmx^oU^yq2vKkF2; z*nSU4nUxFbEM9X-V}De5$<7T{3m!SxWpjb$Y5Z4eK%6*;9>IO4o6ErMbwquhep?dq zt%NWZnxT!6KxEz>3V>O?~D-k3lV?+Yj=b;Z12;@?nHS=3?#sjEs zX=)gcJ#aTgYv;Jdz8Xll%9R!BsK0wg*6VJsKj9gyC^!gX^PXCk0=x#dgNGk{Y2(`7 z=sYC2G?d?Zv2=c-)hA6u7(XZ?UIhqbW%1PYF6HUf(a4Iz3q-2or+DR!IKh`ct3Tj%u_i27INNI?d{0Sfm zuTW$Qy-cLpa>D4u6E>}zJ#jx9P_Z- z4^h;q1PjiNjoywiZz-t?>d>gPYA6L!CGMB%BZ@>r8R0(kB5K=RPlAEWg8jq@`|TZ5l_e-QF-6#ZRrtoiHGfbf=$~BjKR&z1 zNsVqmXiuKzjohUhaawQOXOnECyLIFQwq}#!{<`-*SAFI@8P~DVPs(pDy%6y`Af{J+ zjzz_1?(VtOmQC{}Eu~dCv%*6rclI-n{hcRo`v)jkjl}QT9``#VZQ?{H3`k5a30TBb z8tQiXG|5|iyg+-vKN;v9jC!lK5Ov#ff^4F8a%Wh)<^`OXIigFDp99nzZzS*CPeQ%a zh+7rSg8pz$e92k#Hb?VvZ>lA!-7%fa+Mnlf)GH)X-|E4Yn*L@AjPtRG z+VS-H9dV9IsEVLY@hZ!kk``mVZzox$Vdf7VLeI(ktwQiO0!X9#BHs;3(eTV72|~|b zG!r(k^^gNrdw)kp|AL9TjZhpVNiY^AdQc;iNcB$|)NSZBc<~cRgMv}WuB0EBIQhdv zqt~}it)-w6vH4h+GRZi~cPBjp@Ho4*jq)&s&2A0x=B6~s<(}8^p|nK)TC51CRMUVR z9xgk3`=V7F`4jmcrf?`XPnim6>Pqt13!CVbXpiB--S$YZ{znej;d7K@h&X+@j9ZMEd8JY>7qd8TwL<^`Ct4DI^p^=*@b z`OwaS5QIPc(uVqd6jMmos&$*zVR0WRvr<(M?F?u$(1QHQ#YPhDuk+HKQNToO_nUh=~zEuxJAqZ z(hZ)6J6edoxRuRq+SA?A8mzEh@mr%iteo(tGVFS_n?JwSY(zT!lD{qeI(Z3y;_WmX zhMgQOOtxE4X`D+^V=h~zPJSMLETE@qjugy*^8G3S)s2et)zWj$S4tGA$mfZtv}M+a zJ=>(sI4wB~&_7(NHhSLn#mp|mh5d88xWo?_EfYK=13Pm_yH5$xxCY+UI7mYDXEj67 z@EhG&vlS}RYnd@}Hx{phN|{85leji(9@n%BTEODHQ3wBT0bcsy<0(%}w2}a(G0&d0 zKk-dy$e6GfAsp?h`DH83I@L_sG>ARRqBgEz!qcEmid~ProDL;aJ6X2U#&vspj4zfr z)`hx^IRxN8m%*{}v31t$MvFKa`!KbRQTlu*f0Rp+5Ap1E*d>(&7K+uJxVV=l4}rt? zJmvF=7-gQb&`mqogVbAO%U4xX3OPg?$nQUkmFw?@ajZ&I=t3aUczkB_uSTJ4Z6kYT zF8`H%BYXzXFEw6pg)LIT5{|__VF=LgI;b|;xA%5$2Q+Qhkf81zI68D9^FO)h_Q=h7 zcA3gAr8H>MPa3y&CWFGbPNosPeBvjybU42UF6Ae`--!Ytxw-Wf;sK&~<>TXilf%9^ zU6aGZ@ycT|;H_XjRL%f3tz5f3ks3Tv?C& zNdhWj@AJOZ^aINbg zUvQ%C83=@;zI=8P-cFj?W*Iy&0gikYkJEd)? zXZp^8-uzx}y>FJL8ZvV8*AeYShz8*;o+&28ON+;;P6umjj<1z?;_M!g*9)+*w4tGK zcGoXNj`_{3raJv9`t1F(2V?U$rSST%lwx$B7D)wrHKsO?%Hs6gx@%G;{&QUCh~JZP zbzhzo;88``t{(ddp%v{cfgKby!AC+HW zzGY3CY`DF%Aa=<8Q%EM(k2?iBe|3?E_U4v!>G=gsw1jAur2>FyAqf4}`do+X^dg|L zPtMYo7>&K*pajWcBfKmst{gPFZl{d8lpP^J1kads%r`1s6&{*Mi$;hO>$Yehx1QVf zHawO#3b<>d!uTqnnaq5a!KVE@{mOY%+3i0}RqnkGjo)!5mofLd0{nbPD6ctvF(1_+ z1IvT-MK3+RSJL9FKWfP?cP?)53yZDnzs@_rv^Tv?XKSA@Eu&^XBh~y%lsc zdKj`TT~Y;|&mIa00D@n6Dw%cVCa)cuy)x+13keT9emk_9fd>+9&@Sl>?z<<>wL}x8 zJHMK2ZZ-4=BchLT6wE@mL!6s(Y|zrm}JOwWAOfiM9?u52`#0 zn0d0zBhS2UsR!@MMHzD|Jp{~$#l=s~yUk{N>&i?qF$h_6Pm%Mb!h4;os}B&g8oE$~ z%tB)O%?~D?V-nk2ᣇ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

>et}93645?7=uR^ILVMQsoQaQr9lSC0AmXzEH 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 SEq@8w0ZfgK7(UT=z4m`T5ukej literal 3796 zcmdT`OGs2v82-+gqjPme=T1ou7I|%2v?v^*MGwoHjFm0ILfXzyEecw=Yl76nL}DaK ziy(+B46;pXEU{i9@OFgOOFQ2FCBcJc;hd@lW1ui1$5n$qk{;uyWgWqLtn7;jlC6l7UbP zmhe`=VEsN+J4u(tPq&n!EShAt5om_V9+e_2hus9Fm@U%Kgd6^8s0k*g!wQ*(nsKW} zo`JoQui-fC9|FuawENJ5L;~h{_zKZuB%Wy0t58Ra9wpw<3i;?W5|?3m;LB5Ds}>C< z#lplcd}!>{3(3_}LCpqJT+Y?pDYB(6wLuTFnoc40m%gJ)O*4v8qm3nU6N>Y{ z7JIG~R28zB_gt~T=IBBjs9?*~x`rax203Gt{z1JrY!l|Np!Z_kn*1efGB1I;@Tk^b-BvIAj2JdS`Eiv;!G54n|D9M+a8u93Pt;yUzA z6i;vNLo0c>&`atJsOPqT-H^)BUazmfIv_q$PO2qyisXNr^52;b^;0Adog?Kl6@Ecy zi8@*}1@2d7l~c16v@=rZOe>6xujB|cl>sdg0Xb335lx=OPsj^7SnNV{@*zQu6~OLD i5u$G!;|ynZzW##C!Qp{Z18*)-6;NBVKipj%jeiGrojw`> diff --git a/app/public/favicon.png b/app/public/favicon.png index 109b7634e4468733f200995f584418d58af63b5b..50934a4e14270a44876ee9acb36b9e0ed896e255 100644 GIT binary patch literal 4606 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 delta 168 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%0Dpl&@a#wDRn38C$F1aDisCsrl0-&a@{8!=@sK@ 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 diff --git a/app/public/icon-512.png b/app/public/icon-512.png index 98b5fd6c54c382dbae6863ab0bc978dafa317695..1b7b7b53cb4fc8051bfa1313a0015134c66d2635 100644 GIT binary patch literal 84762 zcmXV11ymbd(+(ay6u06I#oZkO6n7}@Rtm)-xE7b0Dc`0!XkIa)S zcOL`U)~=j1_2wFC{Vy%*S=)Sb3?Om}-ni^3$3NVzKfbRcBg1_7KD9LiEBek$fjr3- zj6y-tAvob2`IAQ1qUk1+^Xh3Qv*Bo_y3#N?^WX{#<9>l9_gTK z*khPrP>PIG_ntFF$e#SyE{Z+>W6z9WeD89)4vxua-Zryl7al}GtkrN>*K_P?K)<4B zw~*QA-n%Sq^rwXec08wb@4Sk3ZXzevJRO!oAwU%#!$c=AJ|z$y7y;}gstRlEl964b zprkatr4U2QQiDe$9-0E%L|O}zBM^hWlxQ7cv3MF73)z6pUSe>Ge-7!;k5HJ|;(!#X zQ~|Y5z?dNdyO52#Vye?-Y7DGuJvvaBEdvIYUKO51Gv$jBI-N%sMB_!TprR)T=%sld zTTkf3ND1YJf)=CiHEhlj7km{B@-t9D2XWC)>D|~;kl}+jYNqdO)YmO;anH^SHu%|2 za1lA-->b6K>Px|N{{~Xcm|!ga<5--4MBFPZgSw-W_ghsjTyrLlBXhG!bSn(IopziE zE%ev4`#UTwcBAQ@x6qydQA8AKSc>3MMBu18*!tyL$|Xi#hrW=*y5&A9<~Jbl8DUX} za3Neif;M9rD>Is;b<|1l%M#dR7$2D>7W>cJRBdn0d0(kk&>*@Vuwe6#ODuGa2x7=U z!Ar^k48Z_o37{ys{{+zmCd+T7Wp&7LtIKh*2}@>lPtn|fW zA=AA!umkdqjZO1MZ0u#KZdYOqn&0&aY4#pZKhoO_|G=R0DG~+|1&Cj#$v`P_p+pbD zvBdR)B*+WJJj;VY?)3Kv+1@v`<6=p;1mCUeiDGu`rM_;9nmgNyQ~K3UJu*l8wI)#p z;aL~uYx+Sc^pA5036j$QqtyiHK#(bkXHV@qSC+f8VK@`=+z4BQaw%;5Z;>GVm?bl1 z)E6)G8axRS`1{1pUb9+b*2fd*N>f@Qwdv{5vj<`-AivcD2w7Q#^_Go z*zYb0MMQrIj4{&^F``({Z}Ll~umIad-?|c*$S}S9+XqX^sf3_jkQy+cMB@|iLO-Ij z@TysfSDPhgZv}4h7xJlxq9YpP)q=@a9q-K2M!&A9N9w|)xw+1+nb==zvd~$KE8%#_ zX^Aluh5Y!4a#8j1;IPXDzq9vfihoPDzkvxrKy+Hw^C?dELLlJYDS(fJVk#Rp8o%n6 z3M&3SuAi2eF;Ma`o%xS9*W;Vp9?x6CjfMxFBf5}2E&m7zc_ikb(kF4oM-1pm;FrF^ ziiXuQ9sf`8@P~*&xHmKyiQJ|(ZIsTXhchKnbmm^78c!o;z704)&jawodDn1E!L5)k z;ZcxUcw*CxwQ`uWuWGs|l=JqI)aO7k0_eX&~OQ*{S>)h1#rf(S^s z3P4pMl|8MKl7De-^os?}%x6ccyp@we6o8DNTuxTM!f@w2rit$1v|!FRrUxI(Up75do5vH6gN9 z_iV$gC;?R+^lN1Q7)*nn?fogxs>=KyHSS0=x)8^gSOQvkRT0Uq0}H;_u*Hc=g{vo* z6lg-Ah9xDnQ-+6(GWBSSc@tyU;Ovz1GcLDWYoL)XNFQ- ziMc#tMAl96)-N%?1bK}5NYt@1nI!lSUy;gJVn2QDl=&2mx3%j8QhNPwt`m~vY>gE{ zjXGuV+AU-qM?TNe<$3; zu`tE@>(FaA&A~-n{IeSpU~Bg+Q&Tqgrbg^up>Gpp1rpyDYbe*deUv(l3)lhH`@k4$0j zmNKgyNzEvFy!Wl!R1%{#xyZOL`~98Z|HNs)iKZ)L1LY<^THj@5bd82H9a^C_umDQ^ z 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

ik4h_Kz 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 From 0b4ad1c99f8011215cd1603d3856d6ee05585b80 Mon Sep 17 00:00:00 2001 From: Hank Date: Fri, 10 Jul 2026 06:27:32 +0000 Subject: [PATCH 02/22] Add ticket-voucher entitlement lookup + document both public APIs GET /api/public/ticket-vouchers?key=&email= returns 0/1/2 free tickets based on donations on/after VOUCHER_SINCE (default 2025-09-04): >= $400 -> 1, >= $1000 -> 2. Same secret/CORS/rate-limit as donor-eligibility; returns only the count. Cutoff and thresholds are env-configurable. Documented both lookup APIs (discount + vouchers) in docs/fluentforms-donor-discount.md with form snippets. Co-Authored-By: Claude Fable 5 --- .env.example | 7 ++ backend/src/config.ts | 6 ++ backend/src/routes/publicLookup.ts | 41 +++++++++- backend/src/services/donors.ts | 20 +++++ docs/fluentforms-donor-discount.md | 122 ++++++++++++++++++++++++++++- 5 files changed, 190 insertions(+), 6 deletions(-) diff --git a/.env.example b/.env.example index c52cdc0..edaaaef 100644 --- a/.env.example +++ b/.env.example @@ -20,6 +20,13 @@ NOCODB_DONOR_OFFLINE_TABLE_ID= # Ice bags granted when a purchase includes ice but the webhook sends only a boolean ICE_BAGS_DEFAULT=3 +# Ticket-voucher entitlement (donor free tickets). Donations on/after +# VOUCHER_SINCE totalling >= TIER1 earn 1 voucher, >= TIER2 earn 2. Bump the +# date each year. NOTE: with no donations after the cutoff, everyone gets 0. +VOUCHER_SINCE=2025-09-04 +VOUCHER_TIER1_MIN=400 +VOUCHER_TIER2_MIN=1000 + # Serve /test with sample QR codes (seeds test personas into the CURRENT table). # Keep this false/empty in production — only enable when pointed at a TEST table. ENABLE_TEST_PAGE=false diff --git a/backend/src/config.ts b/backend/src/config.ts index ab39649..b8941ef 100644 --- a/backend/src/config.ts +++ b/backend/src/config.ts @@ -27,6 +27,12 @@ const schema = z.object({ PUBLIC_LOOKUP_SECRET: z.string().optional(), PUBLIC_LOOKUP_ORIGIN: z.string().default("https://tickets.beartariacampgrounds.com"), + // Ticket-voucher entitlement: donations on/after VOUCHER_SINCE totalling + // >= TIER1 earn 1 voucher, >= TIER2 earn 2. Bump the date each year. + VOUCHER_SINCE: z.string().default("2025-09-04"), + VOUCHER_TIER1_MIN: z.coerce.number().default(400), + VOUCHER_TIER2_MIN: z.coerce.number().default(1000), + // Serve GET /test with sample QR codes. Seeds test personas into the current // NocoDB table, so keep this OFF in production (only enable against a TEST table). ENABLE_TEST_PAGE: z diff --git a/backend/src/routes/publicLookup.ts b/backend/src/routes/publicLookup.ts index 8c283d5..c804b30 100644 --- a/backend/src/routes/publicLookup.ts +++ b/backend/src/routes/publicLookup.ts @@ -26,10 +26,17 @@ export async function publicLookupRoutes(app: FastifyInstance): Promise { }; // Preflight (in case the form sends one). - app.options("/api/public/donor-eligibility", async (_req, reply) => { + const preflight = async (_req: any, reply: any) => { cors(reply); return reply.code(204).send(); - }); + }; + app.options("/api/public/donor-eligibility", preflight); + app.options("/api/public/ticket-vouchers", preflight); + + const checkSecret = (req: any): boolean => { + const { key } = (req.query ?? {}) as { key?: string }; + return !!cfg.PUBLIC_LOOKUP_SECRET && !!key && safeEqual(key, cfg.PUBLIC_LOOKUP_SECRET); + }; app.get( "/api/public/donor-eligibility", @@ -57,4 +64,34 @@ export async function publicLookupRoutes(app: FastifyInstance): Promise { } }, ); + + // Ticket-voucher entitlement: how many free tickets a donor has earned from + // giving on/after VOUCHER_SINCE. Same secret/CORS/rate-limit as above. + // Returns only the count (0/1/2) — no dollar amounts. + app.get( + "/api/public/ticket-vouchers", + { config: { rateLimit: { max: 30, timeWindow: "1 minute" } } }, + async (req, reply) => { + cors(reply); + if (!cfg.PUBLIC_LOOKUP_SECRET || !app.ctx.donors.enabled) { + return reply.code(404).send({ error: "not_available" }); + } + if (!checkSecret(req)) { + return reply.code(401).send({ error: "unauthorized" }); + } + const { email } = (req.query ?? {}) as { email?: string }; + const addr = String(email ?? "").trim(); + if (!addr) return { vouchers: 0 }; + + try { + const cutoff = new Date(cfg.VOUCHER_SINCE); + const { amount } = await app.ctx.donors.amountSince(addr, cutoff); + const vouchers = amount >= cfg.VOUCHER_TIER2_MIN ? 2 : amount >= cfg.VOUCHER_TIER1_MIN ? 1 : 0; + return { vouchers }; + } catch { + // Fail closed — grant no vouchers rather than error. + return { vouchers: 0 }; + } + }, + ); } diff --git a/backend/src/services/donors.ts b/backend/src/services/donors.ts index bd13de8..15909f0 100644 --- a/backend/src/services/donors.ts +++ b/backend/src/services/donors.ts @@ -156,6 +156,26 @@ export class DonorService { source: "transactions", }; } + + /** + * Total Paid donations for an email on/after `cutoff`, summed from the + * transaction tables (the only dated source). Used for ticket-voucher + * entitlement. found=false if donor tables aren't configured or there are no + * transactions for the email at all. + */ + async amountSince(rawEmail: string, cutoff: Date): Promise<{ found: boolean; amount: number }> { + const email = rawEmail.trim(); + if (!email || !this.onlineId || !this.offlineId) return { found: false, amount: 0 }; + const esc = email.replace(/[(),]/g, " "); + const [online, offline] = await Promise.all([ + this.list(this.onlineId, `(Email,eq,${esc})`, 1000), + this.list(this.offlineId, `(Email,eq,${esc})`, 1000), + ]); + const amount = + sumSince(online, "Donation Amount", "Donation Date", cutoff) + + sumSince(offline, "Donation Amount", "Donation Date", cutoff); + return { found: online.length + offline.length > 0, amount }; + } } function num(v: unknown): number { diff --git a/docs/fluentforms-donor-discount.md b/docs/fluentforms-donor-discount.md index dcec3fe..296d7f2 100644 --- a/docs/fluentforms-donor-discount.md +++ b/docs/fluentforms-donor-discount.md @@ -1,8 +1,26 @@ -# FluentForms → donor discount lookup +# FluentForms → donor lookup APIs -FluentForms has no native way to query an external database from a field. This -wires it up with a small Custom JS block that calls our secret-gated endpoint -and unlocks a discount when the entered email belongs to a donor/member. +FluentForms has no native way to query an external database from a field. These +wire it up with a small Custom JS block that calls a secret-gated endpoint on +the ticketing backend. Two endpoints are available (same key, CORS, and rate +limit): + +| Endpoint | Purpose | +|---|---| +| `GET /api/public/donor-eligibility` | Is this email a donor/member? → unlock a discount | +| `GET /api/public/ticket-vouchers` | How many free tickets has this donor earned? → 0 / 1 / 2 | + +Both require `?key=`, are rate-limited (30/min/IP), and +CORS-restricted to `PUBLIC_LOOKUP_ORIGIN` (default +`https://tickets.beartariacampgrounds.com`). Neither returns names or dollar +amounts. The secret is visible in page source, so treat it as deterrence, not +security; rotate it by changing `PUBLIC_LOOKUP_SECRET` and redeploying. + +--- + +## Donor discount lookup + +Unlocks a discount when the entered email belongs to a donor/member. ## Endpoint @@ -124,3 +142,99 @@ curl "https://scan.beartariacampgrounds.com/api/public/donor-eligibility?key=&email= +-> {"vouchers": 0} | {"vouchers": 1} | {"vouchers": 2} +``` + +**Rules** (donations summed on/after the cutoff): + +| Total since cutoff | Vouchers | +|---|---| +| ≥ $1000 | 2 | +| ≥ $400 | 1 | +| otherwise | 0 | + +**Config** (backend `.env`): + +| Var | Default | Meaning | +|---|---|---| +| `VOUCHER_SINCE` | `2025-09-04` | Only donations on/after this date count. Bump each year. | +| `VOUCHER_TIER1_MIN` | `400` | Dollar total for 1 voucher | +| `VOUCHER_TIER2_MIN` | `1000` | Dollar total for 2 vouchers | + +> The count is computed from the **dated transaction tables** (online + offline) +> — the master-list rollups have no dates. Only `Paid` transactions count. + +### Form snippet + +Displays the voucher count and (optionally) sets a hidden field / caps a +quantity. Same pattern as the discount lookup — paste into a Custom HTML element +and set `KEY`. + +```html +

+ +``` + +### Test + +``` +curl "https://scan.beartariacampgrounds.com/api/public/ticket-vouchers?key=&email=" +# -> {"vouchers":2} (>= $1000 since the cutoff) +``` + +> **Heads-up on the cutoff:** with `VOUCHER_SINCE=2025-09-04`, everyone currently +> returns `0` because the donation data in NocoDB ends **2025-05-22** — there are +> no transactions after the cutoff yet. Adjust `VOUCHER_SINCE` (or wait for new +> donations to sync) so the window matches real giving. From 718d1515b0be687c437b7ec026d7ea8ba41b06dd Mon Sep 17 00:00:00 2001 From: Hank Date: Fri, 10 Jul 2026 06:36:39 +0000 Subject: [PATCH 03/22] docs: dedicated ticket-voucher lookup page under fluent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the ticket-voucher API into its own standalone doc (docs/fluentforms-ticket-vouchers.md) — endpoint, 0/1/2 rules, config, form snippet, and curl test — so it's easy to find and hand off for the lookup. The donor-discount doc now links to it instead of duplicating the section. Co-Authored-By: Claude Fable 5 --- docs/fluentforms-donor-discount.md | 94 +--------------------- docs/fluentforms-ticket-vouchers.md | 116 ++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 91 deletions(-) create mode 100644 docs/fluentforms-ticket-vouchers.md diff --git a/docs/fluentforms-donor-discount.md b/docs/fluentforms-donor-discount.md index 296d7f2..6872a0f 100644 --- a/docs/fluentforms-donor-discount.md +++ b/docs/fluentforms-donor-discount.md @@ -147,94 +147,6 @@ member/donor distinction. ## Ticket-voucher entitlement -Returns how many **free tickets** a donor has earned from their giving, based on -donations **on/after a cutoff date** (default `2025-09-04` — "9/4 last year"). - -``` -GET https://scan.beartariacampgrounds.com/api/public/ticket-vouchers?key=&email= --> {"vouchers": 0} | {"vouchers": 1} | {"vouchers": 2} -``` - -**Rules** (donations summed on/after the cutoff): - -| Total since cutoff | Vouchers | -|---|---| -| ≥ $1000 | 2 | -| ≥ $400 | 1 | -| otherwise | 0 | - -**Config** (backend `.env`): - -| Var | Default | Meaning | -|---|---|---| -| `VOUCHER_SINCE` | `2025-09-04` | Only donations on/after this date count. Bump each year. | -| `VOUCHER_TIER1_MIN` | `400` | Dollar total for 1 voucher | -| `VOUCHER_TIER2_MIN` | `1000` | Dollar total for 2 vouchers | - -> The count is computed from the **dated transaction tables** (online + offline) -> — the master-list rollups have no dates. Only `Paid` transactions count. - -### Form snippet - -Displays the voucher count and (optionally) sets a hidden field / caps a -quantity. Same pattern as the discount lookup — paste into a Custom HTML element -and set `KEY`. - -```html -
- -``` - -### Test - -``` -curl "https://scan.beartariacampgrounds.com/api/public/ticket-vouchers?key=&email=" -# -> {"vouchers":2} (>= $1000 since the cutoff) -``` - -> **Heads-up on the cutoff:** with `VOUCHER_SINCE=2025-09-04`, everyone currently -> returns `0` because the donation data in NocoDB ends **2025-05-22** — there are -> no transactions after the cutoff yet. Adjust `VOUCHER_SINCE` (or wait for new -> donations to sync) so the window matches real giving. +The donor **ticket-voucher lookup** (how many free tickets a donor earned) is a +separate endpoint documented on its own page: +[`fluentforms-ticket-vouchers.md`](./fluentforms-ticket-vouchers.md). diff --git a/docs/fluentforms-ticket-vouchers.md b/docs/fluentforms-ticket-vouchers.md new file mode 100644 index 0000000..6f079a5 --- /dev/null +++ b/docs/fluentforms-ticket-vouchers.md @@ -0,0 +1,116 @@ +# FluentForms → ticket-voucher lookup + +Look up, by email, how many **free tickets** a donor has earned from their +giving. Intended for the ticket-rewards / checkout form: enter an email, call +this endpoint, and show / apply the earned vouchers. + +FluentForms can't query an external database from a field natively, so this is +done with a small Custom JS block that calls a secret-gated endpoint on the +ticketing backend. + +## Endpoint + +``` +GET https://scan.beartariacampgrounds.com/api/public/ticket-vouchers?key=&email= +``` + +Returns only the count — never names or dollar amounts: + +```json +{ "vouchers": 0 } // or 1, or 2 +``` + +- `key` = the value of `PUBLIC_LOOKUP_SECRET` (set in the backend `.env`). +- `email` = the donor's email (URL-encoded). +- Rate-limited (30 requests / minute / IP) and CORS-restricted to + `PUBLIC_LOOKUP_ORIGIN` (default `https://tickets.beartariacampgrounds.com`). + +> The secret is visible in page source, so treat it as **deterrence, not +> security** — it only gates a 0/1/2 count. Rotate it by changing +> `PUBLIC_LOOKUP_SECRET` and redeploying. + +## Rules + +Donations are summed for the email across the online + offline transaction +tables, counting only **Paid** rows dated **on/after `VOUCHER_SINCE`**: + +| Total since the cutoff | Vouchers | +|---|---| +| ≥ $1000 | 2 | +| ≥ $400 | 1 | +| otherwise | 0 | + +Configurable in the backend `.env`: + +| Var | Default | Meaning | +|---|---|---| +| `VOUCHER_SINCE` | `2025-09-04` | Only donations on/after this date count. Bump each year. | +| `VOUCHER_TIER1_MIN` | `400` | Dollar total for 1 voucher | +| `VOUCHER_TIER2_MIN` | `1000` | Dollar total for 2 vouchers | + +The count comes from the **dated transaction tables** (the donor master-list +rollups have no dates), so donations must exist in those tables for the window. + +## Form snippet + +Add a **Custom HTML** element to the form and paste this, setting `KEY` to your +`PUBLIC_LOOKUP_SECRET` (and `EMAIL_SELECTOR` if the email field isn't named +`email`). It shows the earned count on email blur and writes it into a hidden +field `free_tickets` you can use for conditional logic or to cap a quantity. + +```html +
+ +``` + +## Test + +``` +curl "https://scan.beartariacampgrounds.com/api/public/ticket-vouchers?key=&email=" +# >= $1000 since cutoff -> {"vouchers":2} +# >= $400 since cutoff -> {"vouchers":1} +# otherwise -> {"vouchers":0} +``` + +Related: [`fluentforms-donor-discount.md`](./fluentforms-donor-discount.md) — the +companion donor-discount eligibility lookup (same key / CORS / rate limit). From b7c77afe02becc51d37a9142dd2009cefead357a Mon Sep 17 00:00:00 2001 From: Hank Date: Mon, 13 Jul 2026 03:23:06 +0000 Subject: [PATCH 04/22] Rework webhook + model for the 2026 Tickets form New form schema: up to 10 named adults, youth 13-16, kids 10-12 / 5-9 / 0-4, donor tier/vouchers (from the lookups), parking/RV/UTV/ice payment fields. - Scannable total = adults + youth + kids 10-12 + kids 5-9 (kids 0-4 free). - Store + display adult names on a good scan; show donor tier, UTV, vouchers. - Ice: payment_ice = 1-4 tickets ($20 each), 1 ticket = 3 bags. - New NocoDB 2026 schema (with Id PK); webhook parses compound names, quantity/payment fields (nested objects or money strings). - Our webhook keeps sending the QR ticket email (FluentForms sends the receipt); from address is now info@beartariacampgrounds.com. Updated /test personas, /webhook-doc, tests, and the app display. Co-Authored-By: Claude Fable 5 --- .env.example | 8 +- app/app/admin.tsx | 13 ++- app/app/index.tsx | 30 +++++- app/lib/api.ts | 6 +- backend/src/config.ts | 8 +- backend/src/fields.ts | 104 +++++++++++--------- backend/src/routes/test.ts | 45 +++++---- backend/src/routes/tickets.ts | 18 +++- backend/src/routes/webhook.ts | 164 +++++++++++++++++++++---------- backend/src/routes/webhookDoc.ts | 95 +++++++++--------- backend/src/test/fakeNocodb.ts | 5 +- backend/src/test/fields.test.ts | 33 ++++--- backend/src/test/redeem.test.ts | 22 ++--- backend/src/ticketService.ts | 19 +++- 14 files changed, 360 insertions(+), 210 deletions(-) diff --git a/.env.example b/.env.example index edaaaef..2fe3055 100644 --- a/.env.example +++ b/.env.example @@ -17,8 +17,10 @@ NOCODB_DONORS_TABLE_ID= NOCODB_DONOR_ONLINE_TABLE_ID= NOCODB_DONOR_OFFLINE_TABLE_ID= -# Ice bags granted when a purchase includes ice but the webhook sends only a boolean -ICE_BAGS_DEFAULT=3 +# Ice: form sells 1-4 ice tickets at $20 each; one ticket = 3 bags. The webhook +# reads payment_ice as a ticket count (1-4) or a dollar total ($20-$80). +ICE_TICKET_PRICE=20 +ICE_BAGS_PER_TICKET=3 # Ticket-voucher entitlement (donor free tickets). Donations on/after # VOUCHER_SINCE totalling >= TIER1 earn 1 voucher, >= TIER2 earn 2. Bump the @@ -33,7 +35,7 @@ ENABLE_TEST_PAGE=false # MailerSend MAILERSEND_API_TOKEN= -MAIL_FROM_EMAIL=tickets@beartariacampgrounds.com +MAIL_FROM_EMAIL=info@beartariacampgrounds.com MAIL_FROM_NAME=Beartaria Campgrounds # Shared secret FluentForms sends in the X-Webhook-Secret header (long random string) diff --git a/app/app/admin.tsx b/app/app/admin.tsx index fd9c121..f492fc9 100644 --- a/app/app/admin.tsx +++ b/app/app/admin.tsx @@ -201,11 +201,14 @@ function TicketCard({ ticket, onAdjust }: { ticket: TicketView; onAdjust: (t: Ti }, [ticket.redeemed, showHistory]); const tags: string[] = []; - if (ticket.extras.carParking) tags.push("🚗 Car"); - if (ticket.extras.rvParking) tags.push("🚐 RV"); - if (ticket.extras.iceAccess) tags.push("🧊 Ice"); - if (ticket.extras.isDonor) tags.push("⭐ Donor"); - if (ticket.extras.freeUnder4 > 0) tags.push(`👶 ${ticket.extras.freeUnder4} free`); + const e = ticket.extras; + if (e.donorTier === "member") tags.push("🐻 Member"); + else if (e.isDonor) tags.push("⭐ Donor"); + if (e.carParking) tags.push("🚗 Car"); + if (e.rvParking) tags.push("🚐 RV"); + if (e.utv) tags.push("🏍️ UTV"); + if (e.iceAccess || ticket.ice.total > 0) tags.push(`🧊 ${ticket.ice.remaining}/${ticket.ice.total}`); + if (e.freeUnder5 > 0) tags.push(`👶 ${e.freeUnder5} free`); return ( diff --git a/app/app/index.tsx b/app/app/index.tsx index 851d9c7..297e1d9 100644 --- a/app/app/index.tsx +++ b/app/app/index.tsx @@ -259,6 +259,7 @@ export default function ScannerScreen() { {ticket.redeemed} of {ticket.total} redeemed · {ticket.remaining} remaining + )} @@ -345,11 +346,14 @@ function BanquetResult({ donor, ticketName }: { donor: DonorLookup | null; ticke function ExtrasRow({ ticket }: { ticket: TicketView }) { const tags: string[] = []; - if (ticket.extras.carParking) tags.push("🚗 Car parking"); - if (ticket.extras.rvParking) tags.push("🚐 RV parking"); - if (ticket.extras.iceAccess || ticket.ice.total > 0) tags.push(`🧊 ${ticket.ice.remaining}/${ticket.ice.total} ice`); - if (ticket.extras.isDonor) tags.push("⭐ Donor"); - if (ticket.extras.freeUnder4 > 0) tags.push(`👶 ${ticket.extras.freeUnder4} under 4 (free)`); + const e = ticket.extras; + if (e.donorTier === "member") tags.push("🐻 Member"); + else if (e.isDonor) tags.push("⭐ Donor"); + if (e.carParking) tags.push("🚗 Car parking"); + if (e.rvParking) tags.push("🚐 RV parking"); + if (e.utv) tags.push("🏍️ UTV/ATV"); + if (e.iceAccess || ticket.ice.total > 0) tags.push(`🧊 ${ticket.ice.remaining}/${ticket.ice.total} ice`); + if (e.freeUnder5 > 0) tags.push(`👶 ${e.freeUnder5} under 5 (free)`); if (!tags.length) return null; return ( @@ -362,6 +366,19 @@ function ExtrasRow({ ticket }: { ticket: TicketView }) { ); } +function AdultNames({ names }: { names: string[] }) { + if (!names.length) return null; + return ( + + {names.map((n, i) => ( + + {n} + + ))} + + ); +} + function ConfirmCard({ ticket, isIce, @@ -393,6 +410,7 @@ function ConfirmCard({ {remaining} of {total} {unit} remaining {redeemed} already redeemed + {!isIce && } {!isIce && } {isIce && total === 0 && This ticket did not prepay for ice.} @@ -489,6 +507,8 @@ const styles = StyleSheet.create({ donorFigureDivider: { width: 1, alignSelf: "stretch", backgroundColor: "rgba(255,255,255,0.35)", marginVertical: 8 }, donorEmail: { color: "rgba(255,255,255,0.85)", fontSize: 14, marginTop: 18 }, + namesBox: { marginTop: 12, alignItems: "center", gap: 3 }, + nameLine: { color: "#fff", fontSize: 18, fontWeight: "600", textAlign: "center" }, tags: { flexDirection: "row", flexWrap: "wrap", justifyContent: "center", gap: 8, marginTop: 14 }, tag: { color: "#fff", backgroundColor: "rgba(255,255,255,0.18)", paddingHorizontal: 10, paddingVertical: 5, borderRadius: 999, fontSize: 13, overflow: "hidden" }, diff --git a/app/lib/api.ts b/app/lib/api.ts index 17f2bea..84dd309 100644 --- a/app/lib/api.ts +++ b/app/lib/api.ts @@ -25,12 +25,16 @@ export interface TicketView { redeemed: number; remaining: number; ice: ResourceCount; + adultNames: string[]; extras: { carParking: boolean; rvParking: boolean; + utv: boolean; iceAccess: boolean; isDonor: boolean; - freeUnder4: number; + donorTier: string; + vouchers: number; + freeUnder5: number; }; ages: { bracket: string; count: number; free: boolean }[]; } diff --git a/backend/src/config.ts b/backend/src/config.ts index b8941ef..df123e5 100644 --- a/backend/src/config.ts +++ b/backend/src/config.ts @@ -17,9 +17,11 @@ const schema = z.object({ NOCODB_DONOR_ONLINE_TABLE_ID: z.string().optional(), NOCODB_DONOR_OFFLINE_TABLE_ID: z.string().optional(), - // Prepaid ice bags granted when a purchase includes ice but the webhook only - // sends a boolean (not an explicit bag count). - ICE_BAGS_DEFAULT: z.coerce.number().default(3), + // Ice: the form sells 1-4 ice "tickets" at $20 each; one ticket = 3 bags. + // The webhook reads payment_ice as either a ticket count (1-4) or a dollar + // total ($20-$80) and stores bags = tickets * ICE_BAGS_PER_TICKET. + ICE_TICKET_PRICE: z.coerce.number().default(20), + ICE_BAGS_PER_TICKET: z.coerce.number().default(3), // Public donor-eligibility lookup (for the FluentForms checkout discount). // Disabled unless a secret is set. Returns only eligibility + tier, never diff --git a/backend/src/fields.ts b/backend/src/fields.ts index c34bff7..5c669e8 100644 --- a/backend/src/fields.ts +++ b/backend/src/fields.ts @@ -1,48 +1,39 @@ /** - * Mapping between the NocoDB "2026 Campground Tickets" table columns, the - * webhook payload keys, and the view we return to the app. - * - * The 2026 table is a clone of the 2025 submission table (per-purchase record - * with age-bracket headcounts, parking/ice flags, donor flag) PLUS four columns - * this system adds: Ticket Code, Redeemed, SubmissionKey, LastScanAt. - * - * If the real column titles differ, change them here in one place. + * Mapping for the "2026 Campground Tickets" NocoDB table, matching the 2026 + * FluentForms "Tickets 2026" schema. Change titles here if the columns differ. */ export const COL = { id: "Id", - name: "Title", // first column in the 2025 table holds the purchaser name + name: "Title", // purchaser full name + adultNames: "Adult Names", // newline-separated list of adult attendee names email: "Email Address", address: "Address", isDonor: "Is Donor", + donorTier: "Donor Tier", // member / donor / "" + vouchers: "Vouchers", + + // Attendee counts by group: + adults: "Adults", + youth: "Youth 13-16", + kids12: "Kids 10-12", + kids9: "Kids 5-9", + kids4: "Kids 0-4", // free — NOT counted toward the scannable total + carParking: "Car Parking", rvParking: "RV Parking", + utv: "UTV", iceAccess: "Ice Access", paymentMethod: "Payment Method", - // Columns this system adds to the table: + // Columns this system manages: code: "Ticket Code", redeemed: "Redeemed", submissionKey: "SubmissionKey", lastScanAt: "LastScanAt", - iceTotal: "Ice Total", // prepaid ice bags - iceRedeemed: "Ice Redeemed", // bags picked up + iceTotal: "Ice Total", + iceRedeemed: "Ice Redeemed", } as const; -/** Age-bracket columns, in order. */ -export const AGE_COLUMNS = [ - "Ages 0-3", - "Ages 4-7", - "Ages 8-12", - "Ages 13-17", - "Ages 18-25", - "Ages 26-45", - "Ages 46-64", - "Ages 65+", -] as const; - -/** Age brackets admitted free and NOT counted as redeemable tickets. */ -export const FREE_AGE_COLUMNS: readonly string[] = ["Ages 0-3"]; - export type NocoRecord = Record & { Id: number }; function num(v: unknown): number { @@ -57,23 +48,40 @@ function bool(v: unknown): boolean { return false; } -/** Total redeemable tickets = sum of age brackets minus the free ones. */ +/** + * Total scannable tickets = everyone except kids 0-4 (who are free): + * adults + youth (13-16) + kids 10-12 + kids 5-9. + */ export function computeTotal(rec: NocoRecord): number { - let total = 0; - for (const col of AGE_COLUMNS) { - if (FREE_AGE_COLUMNS.includes(col)) continue; - total += num(rec[col]); - } - return total; + return num(rec[COL.adults]) + num(rec[COL.youth]) + num(rec[COL.kids12]) + num(rec[COL.kids9]); } -/** Per-bracket breakdown for display. */ +export function computeIceTotal(rec: NocoRecord): number { + return num(rec[COL.iceTotal]); +} + +/** Per-group breakdown for display. */ export function ageBreakdown(rec: NocoRecord): { bracket: string; count: number; free: boolean }[] { - return AGE_COLUMNS.map((col) => ({ - bracket: col.replace(/^Ages /, ""), - count: num(rec[col]), - free: FREE_AGE_COLUMNS.includes(col), - })).filter((b) => b.count > 0); + return [ + { bracket: "Adults", count: num(rec[COL.adults]), free: false }, + { bracket: "Youth 13-16", count: num(rec[COL.youth]), free: false }, + { bracket: "Kids 10-12", count: num(rec[COL.kids12]), free: false }, + { bracket: "Kids 5-9", count: num(rec[COL.kids9]), free: false }, + { bracket: "Kids 0-4", count: num(rec[COL.kids4]), free: true }, + ].filter((b) => b.count > 0); +} + +/** Adult names stored as a newline-separated list. */ +export function parseAdultNames(rec: NocoRecord): string[] { + const raw = rec[COL.adultNames]; + if (Array.isArray(raw)) return raw.map((x) => String(x)).filter(Boolean); + if (typeof raw === "string") { + return raw + .split(/\r?\n/) + .map((s) => s.trim()) + .filter(Boolean); + } + return []; } export interface ResourceCount { @@ -90,20 +98,20 @@ export interface TicketView { redeemed: number; remaining: number; ice: ResourceCount; + adultNames: string[]; extras: { carParking: boolean; rvParking: boolean; + utv: boolean; iceAccess: boolean; isDonor: boolean; - freeUnder4: number; + donorTier: string; + vouchers: number; + freeUnder5: number; }; ages: { bracket: string; count: number; free: boolean }[]; } -export function computeIceTotal(rec: NocoRecord): number { - return num(rec[COL.iceTotal]); -} - export function toView(rec: NocoRecord): TicketView { const total = computeTotal(rec); const redeemed = num(rec[COL.redeemed]); @@ -121,12 +129,16 @@ export function toView(rec: NocoRecord): TicketView { redeemed: iceRedeemed, remaining: Math.max(0, iceTotal - iceRedeemed), }, + adultNames: parseAdultNames(rec), extras: { carParking: bool(rec[COL.carParking]), rvParking: bool(rec[COL.rvParking]), + utv: bool(rec[COL.utv]), iceAccess: bool(rec[COL.iceAccess]), isDonor: bool(rec[COL.isDonor]), - freeUnder4: num(rec["Ages 0-3"]), + donorTier: String(rec[COL.donorTier] ?? ""), + vouchers: num(rec[COL.vouchers]), + freeUnder5: num(rec[COL.kids4]), }, ages: ageBreakdown(rec), }; diff --git a/backend/src/routes/test.ts b/backend/src/routes/test.ts index 4e51d1e..4118f79 100644 --- a/backend/src/routes/test.ts +++ b/backend/src/routes/test.ts @@ -7,57 +7,68 @@ interface Persona { key: string; name: string; email: string; - ages: Record; + adultNames?: string[]; + counts: { adults: number; youth: number; kids12: number; kids9: number; kids4: number }; iceBags?: number; carParking?: boolean; rvParking?: boolean; + utv?: boolean; isDonor?: boolean; + donorTier?: string; exhaust?: boolean; // pre-redeem all tickets so it scans as "exhausted" blurb: string; } +const C = (adults = 0, youth = 0, kids12 = 0, kids9 = 0, kids4 = 0) => ({ adults, youth, kids12, kids9, kids4 }); + // A curated set covering the different attribute combinations to test. const PERSONAS: Persona[] = [ { key: "solo", name: "Solo Sam", email: "solo@test.beartaria", - ages: { "Ages 18-25": 1 }, + adultNames: ["Solo Sam"], + counts: C(1), blurb: "1 ticket, no extras. Check-in mode → green, 1/1.", }, { key: "family", name: "Family Fay", email: "family@test.beartaria", - ages: { "Ages 0-3": 2, "Ages 8-12": 3, "Ages 26-45": 2 }, + adultNames: ["Family Fay", "Frank Fay"], + counts: C(2, 0, 0, 3, 2), // 2 adults + 3 kids(5-9) = 5 scannable; 2 kids 0-4 free iceBags: 3, carParking: true, blurb: - "5 tickets (2 under-4 free), car parking, 3 ice bags. Check-in a few at a time to test QR reuse; then Ice mode.", + "5 tickets (2 adults + 3 kids 5-9; two 0-4 free), car parking, 3 ice bags. Check-in a few at a time to test QR reuse + see adult names; then Ice mode.", }, { key: "donor2", name: "Donor Dan", email: "donor@example.test", - ages: { "Ages 26-45": 2 }, + adultNames: ["Donor Dan", "Donna Dan"], + counts: C(2), rvParking: true, + utv: true, isDonor: true, + donorTier: "member", blurb: - "2 tickets, RV parking, donor-flagged. Banquet mode: this test email has no real donations, so use Banquet's manual email lookup with a real donor's address to see totals.", + "2 tickets, RV + UTV, donor/member. Banquet mode: this test email has no real donations — use Banquet's manual email lookup with a real donor's address.", }, { key: "ice", name: "Ice Ike", email: "ice@test.beartaria", - ages: { "Ages 18-25": 1 }, - iceBags: 3, - blurb: "1 ticket + 3 ice bags. Ice mode → grab all 3 at once, then scan again → exhausted.", + adultNames: ["Ice Ike"], + counts: C(1), + iceBags: 6, // 2 ice tickets + blurb: "1 ticket + 6 ice bags (2 ice tickets). Ice mode → grab bags, then scan again → exhausted.", }, { key: "exhausted", name: "Done Dora", email: "done@test.beartaria", - ages: { "Ages 26-45": 2 }, + counts: C(2), exhaust: true, blurb: "2 tickets, already fully redeemed. Check-in mode → red 'exhausted'.", }, @@ -74,22 +85,22 @@ export async function testRoutes(app: FastifyInstance): Promise { for (const p of PERSONAS) { const result = await createTicket(app.ctx, { name: p.name, + adultNames: p.adultNames, email: p.email, - ages: p.ages, + counts: p.counts, iceBags: p.iceBags, carParking: p.carParking, rvParking: p.rvParking, + utv: p.utv, isDonor: p.isDonor, + donorTier: p.donorTier, submissionKey: `test:${p.key}`, }); // Keep the "exhausted" persona fully redeemed on every load so its state - // is deterministic (compute the total from the persona's own age counts, - // since NocoDB's create response may not echo them back). + // is deterministic (total = scannable count from the persona's counts). if (p.exhaust) { - const total = Object.entries(p.ages) - .filter(([col]) => col !== "Ages 0-3") - .reduce((s, [, n]) => s + n, 0); - await app.ctx.nocodb.update(result.record.Id, { [COL.redeemed]: total }); + const { adults, youth, kids12, kids9 } = p.counts; + await app.ctx.nocodb.update(result.record.Id, { [COL.redeemed]: adults + youth + kids12 + kids9 }); } cards.push({ code: result.code, diff --git a/backend/src/routes/tickets.ts b/backend/src/routes/tickets.ts index c99c2b8..eaa2a67 100644 --- a/backend/src/routes/tickets.ts +++ b/backend/src/routes/tickets.ts @@ -167,11 +167,16 @@ export async function ticketRoutes(app: FastifyInstance): Promise { schema: { body: { type: "object", - required: ["name", "ages"], + required: ["name"], properties: { name: { type: "string", minLength: 1 }, email: { type: "string" }, - ages: { type: "object" }, + adults: { type: "integer", minimum: 0 }, + youth: { type: "integer", minimum: 0 }, + kids12: { type: "integer", minimum: 0 }, + kids9: { type: "integer", minimum: 0 }, + kids4: { type: "integer", minimum: 0 }, + adultNames: { type: "array", items: { type: "string" } }, sendEmail: { type: "boolean" }, }, }, @@ -182,8 +187,15 @@ export async function ticketRoutes(app: FastifyInstance): Promise { const submissionKey = `manual:${Date.now()}:${Math.trunc(Math.random() * 1e9)}`; const result = await createTicket(app.ctx, { name: b.name, + adultNames: b.adultNames, email: b.email ?? "", - ages: b.ages, + counts: { + adults: b.adults ?? 1, + youth: b.youth ?? 0, + kids12: b.kids12 ?? 0, + kids9: b.kids9 ?? 0, + kids4: b.kids4 ?? 0, + }, submissionKey, }); if (b.sendEmail && b.email && !app.ctx.mailer.isBlockedRecipient(b.email)) { diff --git a/backend/src/routes/webhook.ts b/backend/src/routes/webhook.ts index b1352a8..9d96961 100644 --- a/backend/src/routes/webhook.ts +++ b/backend/src/routes/webhook.ts @@ -1,6 +1,6 @@ import { createHash, timingSafeEqual } from "node:crypto"; import type { FastifyInstance } from "fastify"; -import { AGE_COLUMNS, toBool, toNumber } from "../fields.js"; +import { toBool, toNumber } from "../fields.js"; import { createTicket } from "../ticketService.js"; import { renderQrPng } from "../services/qrcode.js"; @@ -11,18 +11,48 @@ function safeEqual(a: string, b: string): boolean { return timingSafeEqual(ba, bb); } -// Map webhook payload keys -> NocoDB age-column titles. Keys are what you map -// the FluentForms fields to in the webhook feed. -const AGE_KEY_TO_COL: Record = { - ages_0_3: "Ages 0-3", - ages_4_7: "Ages 4-7", - ages_8_12: "Ages 8-12", - ages_13_17: "Ages 13-17", - ages_18_25: "Ages 18-25", - ages_26_45: "Ages 26-45", - ages_46_64: "Ages 46-64", - ages_65: "Ages 65+", -}; +/** Read a FluentForms compound name field, given as a nested object + * (`names: {first_name,...}`) or flattened bracket keys (`names[first_name]`). */ +function nameGroup(body: Record, base: string): string { + const obj = body[base]; + let first: any, middle: any, last: any; + if (obj && typeof obj === "object") { + ({ first_name: first, middle_name: middle, last_name: last } = obj); + } else { + first = body[`${base}[first_name]`]; + middle = body[`${base}[middle_name]`]; + last = body[`${base}[last_name]`]; + } + return [first, middle, last] + .map((x) => (x == null ? "" : String(x).trim())) + .filter(Boolean) + .join(" "); +} + +/** Read an item_quantity / payment field's numeric value (handles nested + * objects like {quantity} / {value} and money strings like "$40.00"). */ +function qty(v: any): number { + if (v == null || v === "") return 0; + if (typeof v === "object") return toNumber(v.quantity ?? v.value ?? v.item_quantity ?? v.amount ?? 0); + if (typeof v === "string") return toNumber(v.replace(/[^0-9.\-]/g, "")); + return toNumber(v); +} + +/** A payment/extra field counts as "selected" if it has a meaningful value. + * Donor (free) items can be $0, so a non-empty, non-"no"/"0" value also counts. */ +function selected(v: any): boolean { + if (v == null || v === "") return false; + if (typeof v === "object") { + if ("selected" in v) return toBool((v as any).selected); + return qty(v) > 0 || Object.keys(v).length > 0; + } + const s = String(v).trim().toLowerCase(); + if (!s || s === "no" || s === "0" || s === "$0" || s === "$0.00" || s === "false" || s === "none") return false; + return true; +} + +// Adult name field bases, in order (purchaser first). +const ADULT_NAME_BASES = ["names", "names_1", "names_2", "names_3", "names_4", "names_5", "names_6", "names_7", "names_8", "names_9"]; export async function webhookRoutes(app: FastifyInstance): Promise { const handler = async (req: any, reply: any) => { @@ -31,57 +61,87 @@ export async function webhookRoutes(app: FastifyInstance): Promise { return reply.code(401).send({ error: "unauthorized" }); } - const body = (req.body ?? {}) as Record; - const name = String(body.name ?? "").trim(); + const body = (req.body ?? {}) as Record; + + // Purchaser = the first adult name group; fall back to a plain `name` field. + const name = nameGroup(body, "names") || String(body.name ?? "").trim(); const email = String(body.email ?? "").trim(); - if (!name || !email) { - return reply.code(400).send({ error: "missing_fields", detail: "name and email are required" }); + if (!name) { + return reply.code(400).send({ error: "missing_fields", detail: "purchaser name is required" }); } - // Build age-bracket counts from whichever keys were provided. - const ages: Record = {}; - for (const [key, col] of Object.entries(AGE_KEY_TO_COL)) { - if (body[key] !== undefined && body[key] !== null && body[key] !== "") { - ages[col] = toNumber(body[key]); - } - } - const anyAge = AGE_COLUMNS.some((c) => (ages[c] ?? 0) > 0); - if (!anyAge) { - return reply.code(400).send({ error: "no_tickets", detail: "no age-bracket counts provided" }); + // Adult attendee names (non-empty groups, in order). + const adultNames = ADULT_NAME_BASES.map((b) => nameGroup(body, b)).filter(Boolean); + + // Attendee counts. + const counts = { + adults: qty(body.item_quantity_adult_ticket_reg) + qty(body.item_quantity_adult_ticket_donor), + youth: qty(body.item_quantity_youth_ticket_reg) + qty(body.item_quantity_youth_ticket_donor), + kids12: qty(body.item_quantity_kids_12), + kids9: qty(body.item_quantity_kids_9), + kids4: qty(body.item_quantity_kids_4), + }; + const scannable = counts.adults + counts.youth + counts.kids12 + counts.kids9; + if (scannable <= 0) { + // Nothing to check in at the gate. Log the payload so we can calibrate. + req.log.warn({ body }, "webhook: no scannable tickets in submission"); + return reply.code(400).send({ error: "no_tickets", detail: "no scannable tickets (adults/youth/kids 5+)" }); } - // Idempotency key: prefer a stable submission id, else hash the content. - const submissionId = body.submission_id ?? body.submissionId ?? body.entry_id; + // Donor info (hidden fields from the eligibility/voucher lookups) + radio. + const donorTier = String(body.donor_tier ?? "").trim(); + const isDonor = + donorTier === "member" || + donorTier === "donor" || + toBool(body.donor_eligible) || + selected(body.input_radio); // "Are you a campground donor?" + const vouchers = qty(body.vouchers); + + // Extras (best-effort from payment fields — donor variants may be free/$0). + const carParking = selected(body.payment_parking_reg) || selected(body.payment_parking_donor); + const rvParking = selected(body.payment_rv_reg) || selected(body.payment_rv_donor); + const utv = selected(body.payment_utv_reg) || selected(body.payment_utv_donor); + // Ice: payment_ice is either a ticket count (1-4) or a dollar total + // ($20-$80). One ice ticket = ICE_BAGS_PER_TICKET bags. + const iceRaw = qty(body.payment_ice); + const iceTickets = iceRaw >= app.ctx.config.ICE_TICKET_PRICE ? Math.round(iceRaw / app.ctx.config.ICE_TICKET_PRICE) : Math.round(iceRaw); + const iceBags = Math.max(0, iceTickets) * app.ctx.config.ICE_BAGS_PER_TICKET; + const iceAccess = iceBags > 0 || selected(body.input_radio_7); + + const address = + body.address_1 && typeof body.address_1 === "object" + ? Object.values(body.address_1).filter(Boolean).join(", ") + : body.address_1 !== undefined + ? String(body.address_1) + : undefined; + + // Idempotency: prefer a stable submission id, else hash the content. + const submissionId = body.submission_id ?? body.submissionId ?? body.entry_id ?? body.id; const submissionKey = submissionId ? `sub:${String(submissionId)}` : "hash:" + createHash("sha256") - .update(`${email}|${name}|${JSON.stringify(ages)}`) + .update(`${email}|${name}|${JSON.stringify(counts)}`) .digest("hex") .slice(0, 32); - // Ice: prefer an explicit bag count; else grant the default when a boolean - // ice option is truthy; else 0. - let iceBags = 0; - if (body.ice_bags !== undefined && body.ice_bags !== null && body.ice_bags !== "") { - iceBags = toNumber(body.ice_bags); - } else if (body.ice_access !== undefined && toBool(body.ice_access)) { - iceBags = app.ctx.config.ICE_BAGS_DEFAULT; - } - let result: Awaited>; try { result = await createTicket(app.ctx, { name, + adultNames, email, - address: body.address !== undefined ? String(body.address) : undefined, - isDonor: body.is_donor !== undefined ? toBool(body.is_donor) : undefined, - carParking: body.car_parking !== undefined ? toBool(body.car_parking) : undefined, - rvParking: body.rv_parking !== undefined ? toBool(body.rv_parking) : undefined, - iceAccess: body.ice_access !== undefined ? toBool(body.ice_access) : undefined, + address, + isDonor, + donorTier, + vouchers, + counts, + carParking, + rvParking, + utv, + iceAccess, iceBags, paymentMethod: body.payment_method !== undefined ? String(body.payment_method) : undefined, - ages, submissionKey, }); } catch (e: any) { @@ -93,9 +153,13 @@ export async function webhookRoutes(app: FastifyInstance): Promise { return { status: "duplicate", code: result.code }; } - // Send the ticket email. If it fails, the row already exists — report 502 - // so the failure is visible in FluentForms' delivery log; the ticket can be - // re-sent later via POST /api/tickets/:code/resend-email. + // Send the ticket QR email (FluentForms sends the receipt separately). If it + // fails, the row already exists — report 502 so it's visible in the feed + // log; re-send later via POST /api/tickets/:code/resend-email. + if (!email) { + req.log.warn({ code: result.code }, "webhook: ticket created but no email to send to"); + return { status: "created", code: result.code, emailSent: false, emailSkipped: "no_email" }; + } if (app.ctx.mailer.isBlockedRecipient(email)) { req.log.warn({ email }, "webhook: recipient blocked by MAIL_TEST_RECIPIENTS; skipping send"); return { status: "created", code: result.code, emailSent: false, emailSkipped: "trial_restriction" }; @@ -103,13 +167,11 @@ export async function webhookRoutes(app: FastifyInstance): Promise { try { const qr = await renderQrPng(result.code); - const quantity = // redeemable total for the email copy - AGE_COLUMNS.filter((c) => c !== "Ages 0-3").reduce((s, c) => s + (ages[c] ?? 0), 0); await app.ctx.mailer.sendTicket({ toEmail: email, toName: name, code: result.code, - quantity, + quantity: scannable, qrPng: qr, }); } catch (e: any) { diff --git a/backend/src/routes/webhookDoc.ts b/backend/src/routes/webhookDoc.ts index 89a1b34..8f7bd8a 100644 --- a/backend/src/routes/webhookDoc.ts +++ b/backend/src/routes/webhookDoc.ts @@ -11,29 +11,26 @@ interface Field { } const FIELDS: Field[] = [ - { key: "name", req: "required", type: "text", desc: "Purchaser's full name." }, - { key: "email", req: "required", type: "email", desc: "Purchaser's email — the QR ticket is sent here." }, - { - key: "submission_id", - req: "optional", - type: "text/number", - desc: "Form entry/submission ID. Used for idempotency so retries or double-submits don't create duplicate tickets. If omitted, a hash of name+email+counts is used instead. (Aliases: submissionId, entry_id.)", - }, - { key: "ages_0_3", req: "optional", type: "number", desc: "Headcount ages 0–3. Admitted free — NOT counted toward redeemable tickets." }, - { key: "ages_4_7", req: "optional", type: "number", desc: "Headcount ages 4–7." }, - { key: "ages_8_12", req: "optional", type: "number", desc: "Headcount ages 8–12." }, - { key: "ages_13_17", req: "optional", type: "number", desc: "Headcount ages 13–17." }, - { key: "ages_18_25", req: "optional", type: "number", desc: "Headcount ages 18–25." }, - { key: "ages_26_45", req: "optional", type: "number", desc: "Headcount ages 26–45." }, - { key: "ages_46_64", req: "optional", type: "number", desc: "Headcount ages 46–64." }, - { key: "ages_65", req: "optional", type: "number", desc: "Headcount ages 65+." }, - { key: "ice_bags", req: "optional", type: "number", desc: "Prepaid ice bags. If omitted and ice_access is truthy, defaults to the configured amount (3)." }, - { key: "ice_access", req: "optional", type: "yes/no", desc: "Whether they bought ice access. Accepts 1/0, true/false, yes/no." }, - { key: "car_parking", req: "optional", type: "yes/no", desc: "Car parking pass." }, - { key: "rv_parking", req: "optional", type: "yes/no", desc: "RV parking pass." }, - { key: "is_donor", req: "optional", type: "yes/no", desc: "Donor flag." }, - { key: "address", req: "optional", type: "text", desc: "Mailing address." }, - { key: "payment_method", req: "optional", type: "text", desc: "Payment method label." }, + { key: "names", req: "required", type: "name (compound)", desc: "Purchaser / Adult #1 — object {first_name, middle_name, last_name}. Also accepts flat names[first_name] keys." }, + { key: "names_1 … names_9", req: "optional", type: "name (compound)", desc: "Additional adult attendee names (Adults #2–#10). Empty groups are ignored. Stored as the adult-name list shown at the gate." }, + { key: "email", req: "optional", type: "email", desc: "Purchaser email — the QR ticket is sent here (FluentForms sends the receipt separately)." }, + { key: "address_1", req: "optional", type: "address (compound)", desc: "Mailing address object; joined into one line." }, + { key: "item_quantity_adult_ticket_reg", req: "required", type: "quantity", desc: "Adult tickets (regular)." }, + { key: "item_quantity_adult_ticket_donor", req: "required", type: "quantity", desc: "Adult tickets (donor). Added to the regular adults." }, + { key: "item_quantity_youth_ticket_reg / _donor", req: "optional", type: "quantity", desc: "Youth 13-16 tickets (regular + donor)." }, + { key: "item_quantity_kids_12", req: "optional", type: "quantity", desc: "Kids 10-12. Counts toward the scannable total." }, + { key: "item_quantity_kids_9", req: "optional", type: "quantity", desc: "Kids 5-9. Counts toward the scannable total." }, + { key: "item_quantity_kids_4", req: "optional", type: "quantity", desc: "Kids 0-4. FREE — NOT counted toward the scannable ticket total." }, + { key: "donor_tier", req: "optional", type: "hidden", desc: "member / donor / empty (from the donor-eligibility lookup)." }, + { key: "donor_eligible", req: "optional", type: "hidden", desc: "true / false (from the donor-eligibility lookup)." }, + { key: "vouchers", req: "optional", type: "hidden", desc: "Integer voucher count (from the ticket-voucher lookup)." }, + { key: "input_radio", req: "optional", type: "choice", desc: "'Are you a campground donor?' — also used as a donor signal." }, + { key: "payment_parking_reg / _donor", req: "optional", type: "payment", desc: "Car parking. Flagged if either variant is selected." }, + { key: "payment_rv_reg / _donor", req: "optional", type: "payment", desc: "RV. Flagged if either variant is selected." }, + { key: "payment_utv_reg / _donor", req: "optional", type: "payment", desc: "ATV/UTV. Flagged if either variant is selected." }, + { key: "payment_ice", req: "optional", type: "payment", desc: "Ice tickets (1-4 at $20 each). One ice ticket = 3 bags; stored as bags = tickets × 3. Accepts a ticket count (1-4) or a dollar total ($20-$80)." }, + { key: "payment_method", req: "optional", type: "payment", desc: "Payment method label." }, + { key: "id / submission_id", req: "optional", type: "text", desc: "Entry/submission id for idempotency (retries won't duplicate). Falls back to a content hash." }, ]; function esc(s: string): string { @@ -48,28 +45,34 @@ export async function webhookDocRoutes(app: FastifyInstance): Promise { const rows = FIELDS.map( (f) => ` - ${f.key} + ${esc(f.key)} ${f.req} - ${f.type} + ${esc(f.type)} ${esc(f.desc)} `, ).join(""); const exampleJson = esc(`{ - "name": "Jane Bear", + "id": "412", + "names": { "first_name": "Jane", "last_name": "Bear" }, + "names_1": { "first_name": "John", "last_name": "Bear" }, "email": "jane@example.com", - "submission_id": "12345", - "ages_0_3": 2, - "ages_8_12": 3, - "ages_26_45": 2, - "car_parking": "yes", - "ice_access": "yes" + "item_quantity_adult_ticket_reg": 2, + "item_quantity_adult_ticket_donor": 0, + "item_quantity_youth_ticket_reg": 1, + "item_quantity_kids_9": 2, + "item_quantity_kids_4": 2, + "donor_tier": "member", + "vouchers": 2, + "payment_parking_reg": "$40.00", + "payment_ice": 2, + "payment_method": "stripe" }`); const exampleCurl = esc(`curl -X POST ${WEBHOOK_URL} \\ -H "Content-Type: application/json" \\ -H "X-Webhook-Secret: " \\ - -d '{"name":"Jane Bear","email":"jane@example.com","submission_id":"12345","ages_26_45":2,"ice_access":"yes"}'`); + -d @submission.json`); const PAGE = ` @@ -82,7 +85,7 @@ const PAGE = ` :root { color-scheme: dark; } * { box-sizing: border-box; } body { margin: 0; background: #0f1a12; color: #eaf2ec; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif; line-height: 1.55; } - .wrap { max-width: 820px; margin: 0 auto; padding: 28px 20px 64px; } + .wrap { max-width: 900px; margin: 0 auto; padding: 28px 20px 64px; } h1 { font-size: 26px; margin: 0 0 4px; } h2 { font-size: 20px; margin: 32px 0 10px; border-bottom: 1px solid #24382a; padding-bottom: 6px; } .sub { color: #9db3a4; margin: 0 0 8px; } @@ -104,31 +107,32 @@ const PAGE = `
-

🐻 Camp Scan — Purchase Webhook

-

How the FluentForms ticket checkout notifies the ticketing backend to create a ticket and email the QR code.

+

🐻 Camp Scan — Purchase Webhook (Tickets 2026)

+

How the FluentForms "Tickets 2026" checkout notifies the ticketing backend to create a ticket and email the QR code.

Endpoint  POST ${WEBHOOK_URL}
Auth header  X-Webhook-Secret: <the shared WEBHOOK_SECRET>
-
Body format  JSON (application/json) or form-encoded — both accepted.
+
Body format  JSON (application/json) or form-encoded — both accepted. Send all form fields.

What it does

-

On a valid request the backend generates a unique ticket code, creates a row in the "2026 Campground Tickets" NocoDB table, renders a QR code, and emails it to the purchaser (subject: "2026 Beartaria Campgrounds Tickets"). The total number of redeemable tickets is the sum of the age-bracket counts, excluding ages 0–3 (who are free).

+

On a valid request the backend generates a unique ticket code, creates a NocoDB row, and emails the QR code to the purchaser (subject "2026 Beartaria Campgrounds Tickets"). FluentForms sends the payment receipt separately.

+

Scannable ticket total = adults + youth (13-16) + kids 10-12 + kids 5-9. Kids 0-4 are free and not counted. Each adult name provided is stored and shown to gate staff on a successful scan.

Fields

${rows}
KeyRequiredTypeDescription
-

At least one non-zero age-bracket count is required (otherwise there are no tickets to issue). Booleans accept 1/0, true/false, or yes/no.

+

Compound name fields arrive as objects (names: {first_name,…}) or flattened names[first_name] keys — both handled. Quantity/payment fields accept numbers, money strings ("$40.00"), or {quantity} objects.

Idempotency

-

Send a stable submission_id. If the backend sees the same one again it returns {"status":"duplicate"} without creating a second ticket or re-sending email — so FluentForms retries and accidental double-submits are safe.

+

Send a stable id / submission_id. A repeat returns {"status":"duplicate"} without creating a second ticket or re-emailing — safe for retries and double-submits.

Example payload

${exampleJson}
-

This issues 5 redeemable tickets (3×8–12 + 2×26–45; the two 0–3 are free), with car parking and 3 ice bags.

+

This issues 5 scannable tickets (2 adults + 1 youth + 2 kids 5-9; the two kids 0-4 are free), member donor with 2 vouchers, car parking, and 6 bags of ice (2 ice tickets).

Test with curl

${exampleCurl}
@@ -139,7 +143,7 @@ const PAGE = ` 200{"status":"created","code":"BC26-…","emailSent":true}Ticket created and emailed. 200{"status":"duplicate","code":"BC26-…"}Same submission already processed — no-op. - 400{"error":"missing_fields"} / "no_tickets"Missing name/email, or no age counts. + 400{"error":"missing_fields"} / "no_tickets"Missing purchaser name, or zero scannable tickets. 401{"error":"unauthorized"}Missing or wrong X-Webhook-Secret. 502{"status":"created","emailSent":false,…}Ticket row created but the email failed — re-send from the admin app. @@ -148,11 +152,10 @@ const PAGE = `

FluentForms setup

  1. On the ticket form: Settings & Integrations → Webhook → Add Webhook.
  2. -
  3. Request URL: ${WEBHOOK_URL}
  4. -
  5. Request Method: POST  ·  Format: JSON
  6. +
  7. Request URL: ${WEBHOOK_URL}  ·  Method: POST  ·  Format: JSON
  8. Request Headers: add X-Webhook-Secret = the shared secret.
  9. -
  10. Request Body: map each form field to the keys in the table above.
  11. -
  12. Save, then submit a test purchase and confirm the QR email arrives.
  13. +
  14. Request Body: send all fields (the field names above are the FluentForms field keys).
  15. +
  16. Save, submit a test purchase, and confirm the QR email arrives.
Beartaria Campgrounds · scan.beartariacampgrounds.com
diff --git a/backend/src/test/fakeNocodb.ts b/backend/src/test/fakeNocodb.ts index 46cbd89..9a158f8 100644 --- a/backend/src/test/fakeNocodb.ts +++ b/backend/src/test/fakeNocodb.ts @@ -86,14 +86,13 @@ export function fakeContext(db: FakeNocoDB): AppContext { export async function seedTicket( db: FakeNocoDB, - opts: { code: string; name?: string; email?: string; ages?: Record; redeemed?: number }, + opts: { code: string; name?: string; email?: string; adults?: number; redeemed?: number }, ): Promise { - const ages = opts.ages ?? { "Ages 18-25": 2, "Ages 26-45": 3, "Ages 0-3": 1 }; return db.create({ [COL.code]: opts.code, [COL.name]: opts.name ?? "Test Bear", [COL.email]: opts.email ?? "test@example.com", + [COL.adults]: opts.adults ?? 5, [COL.redeemed]: opts.redeemed ?? 0, - ...ages, }); } diff --git a/backend/src/test/fields.test.ts b/backend/src/test/fields.test.ts index 2287a11..834de59 100644 --- a/backend/src/test/fields.test.ts +++ b/backend/src/test/fields.test.ts @@ -2,45 +2,52 @@ import { describe, it, expect } from "vitest"; import { computeTotal, toView, COL } from "../fields.js"; describe("computeTotal", () => { - it("sums age brackets but excludes Ages 0-3 (free)", () => { + it("sums adults + youth + kids 10-12 + kids 5-9, excluding kids 0-4 (free)", () => { const rec = { Id: 1, - "Ages 0-3": 2, // free, not counted - "Ages 4-7": 1, - "Ages 18-25": 2, - "Ages 26-45": 1, + [COL.adults]: 2, + [COL.youth]: 1, + [COL.kids12]: 1, + [COL.kids9]: 1, + [COL.kids4]: 3, // free, not counted }; - expect(computeTotal(rec)).toBe(4); + expect(computeTotal(rec)).toBe(5); }); it("coerces string counts and treats blanks as 0", () => { - const rec = { Id: 1, "Ages 18-25": "3", "Ages 26-45": "" } as any; + const rec = { Id: 1, [COL.adults]: "3", [COL.youth]: "" } as any; expect(computeTotal(rec)).toBe(3); }); }); describe("toView", () => { - it("derives remaining and surfaces extras", () => { + it("derives remaining and surfaces adult names, donor tier, and extras", () => { const rec = { Id: 7, [COL.code]: "BC26-ABCD-2345", [COL.name]: "Jane Bear", [COL.email]: "jane@example.com", + [COL.adultNames]: "Jane Bear\nJohn Bear", [COL.redeemed]: 2, + [COL.adults]: 2, + [COL.youth]: 3, + [COL.kids4]: 1, [COL.carParking]: true, [COL.iceAccess]: "yes", - "Ages 0-3": 1, - "Ages 18-25": 2, - "Ages 26-45": 3, + [COL.donorTier]: "member", + [COL.vouchers]: 2, }; const v = toView(rec); expect(v.total).toBe(5); expect(v.redeemed).toBe(2); expect(v.remaining).toBe(3); + expect(v.adultNames).toEqual(["Jane Bear", "John Bear"]); expect(v.extras.carParking).toBe(true); expect(v.extras.iceAccess).toBe(true); expect(v.extras.rvParking).toBe(false); - expect(v.extras.freeUnder4).toBe(1); - expect(v.ages.find((a) => a.bracket === "0-3")?.free).toBe(true); + expect(v.extras.donorTier).toBe("member"); + expect(v.extras.vouchers).toBe(2); + expect(v.extras.freeUnder5).toBe(1); + expect(v.ages.find((a) => a.bracket === "Kids 0-4")?.free).toBe(true); }); }); diff --git a/backend/src/test/redeem.test.ts b/backend/src/test/redeem.test.ts index 72738a6..b2255e1 100644 --- a/backend/src/test/redeem.test.ts +++ b/backend/src/test/redeem.test.ts @@ -6,7 +6,7 @@ import { COL } from "../fields.js"; describe("redeem", () => { it("checks in a single walk-up (default count 1)", async () => { const db = new FakeNocoDB(); - await seedTicket(db, { code: "BC26-AAAA-1111", ages: { "Ages 26-45": 4 } }); + await seedTicket(db, { code: "BC26-AAAA-1111", adults: 4 }); const ctx = fakeContext(db); const r = await redeem(ctx, "BC26-AAAA-1111", 1); expect(r.ok).toBe(true); @@ -20,7 +20,7 @@ describe("redeem", () => { it("supports group check-in and QR reuse across visits", async () => { const db = new FakeNocoDB(); // Party of 7 (2 free under-4 not counted): total 5. - await seedTicket(db, { code: "BC26-FAM-0001", ages: { "Ages 0-3": 2, "Ages 26-45": 2, "Ages 8-12": 3 } }); + await seedTicket(db, { code: "BC26-FAM-0001", adults: 5 }); const ctx = fakeContext(db); const first = await redeem(ctx, "BC26-FAM-0001", 2); // father + son @@ -36,7 +36,7 @@ describe("redeem", () => { it("rejects over-redemption without mutating", async () => { const db = new FakeNocoDB(); - await seedTicket(db, { code: "BC26-BBBB-2222", ages: { "Ages 26-45": 2 } }); + await seedTicket(db, { code: "BC26-BBBB-2222", adults: 2 }); const ctx = fakeContext(db); const r = await redeem(ctx, "BC26-BBBB-2222", 5); expect(r.ok).toBe(false); @@ -46,7 +46,7 @@ describe("redeem", () => { it("allows negative count to undo, clamped at zero", async () => { const db = new FakeNocoDB(); - await seedTicket(db, { code: "BC26-CCCC-3333", ages: { "Ages 26-45": 3 }, redeemed: 2 }); + await seedTicket(db, { code: "BC26-CCCC-3333", adults: 3, redeemed: 2 }); const ctx = fakeContext(db); const r = await redeem(ctx, "BC26-CCCC-3333", -5); expect(r.ok).toBe(true); @@ -55,7 +55,7 @@ describe("redeem", () => { it("writes an audit entry on each successful check-in and undo", async () => { const db = new FakeNocoDB(); - await seedTicket(db, { code: "BC26-AUDT-0001", ages: { "Ages 26-45": 4 } }); + await seedTicket(db, { code: "BC26-AUDT-0001", adults: 4 }); const ctx = fakeContext(db); await redeem(ctx, "BC26-AUDT-0001", 2); await redeem(ctx, "BC26-AUDT-0001", -1); @@ -67,7 +67,7 @@ describe("redeem", () => { it("does not audit a no-op (undo when nothing redeemed)", async () => { const db = new FakeNocoDB(); - await seedTicket(db, { code: "BC26-AUDT-0002", ages: { "Ages 26-45": 3 }, redeemed: 0 }); + await seedTicket(db, { code: "BC26-AUDT-0002", adults: 3, redeemed: 0 }); const ctx = fakeContext(db); await redeem(ctx, "BC26-AUDT-0002", -2); // clamps to 0, delta 0 expect((ctx.audit as any).entries).toHaveLength(0); @@ -77,7 +77,7 @@ describe("redeem", () => { const db = new FakeNocoDB(); await seedTicket(db, { code: "BC26-ICE-0003", - ages: { "Ages 26-45": 2 }, + adults: 2, }); // Give the ticket 3 prepaid ice bags. db.rows[0]["Ice Total"] = 3; @@ -112,7 +112,7 @@ describe("redeem", () => { it("surfaces db_error when the update fails", async () => { const db = new FakeNocoDB(); - await seedTicket(db, { code: "BC26-DDDD-4444", ages: { "Ages 26-45": 3 } }); + await seedTicket(db, { code: "BC26-DDDD-4444", adults: 3 }); db.failNext = true; const ctx = fakeContext(db); const r = await redeem(ctx, "BC26-DDDD-4444", 1); @@ -122,7 +122,7 @@ describe("redeem", () => { it("CONCURRENCY: 20 parallel single check-ins on a 5-ticket code yield exactly 5", async () => { const db = new FakeNocoDB(8); - await seedTicket(db, { code: "BC26-RACE-0005", ages: { "Ages 26-45": 5 } }); + await seedTicket(db, { code: "BC26-RACE-0005", adults: 5 }); const ctx = fakeContext(db); const results = await Promise.all( @@ -137,7 +137,7 @@ describe("redeem", () => { describe("lookupByCode", () => { it("returns the ticket view without mutating", async () => { const db = new FakeNocoDB(); - await seedTicket(db, { code: "BC26-LOOK-0001", ages: { "Ages 26-45": 3 } }); + await seedTicket(db, { code: "BC26-LOOK-0001", adults: 3 }); const ctx = fakeContext(db); const r = await lookupByCode(ctx, "BC26-LOOK-0001"); expect(r.ok && r.found && r.ticket.remaining).toBe(3); @@ -159,7 +159,7 @@ describe("createTicket idempotency", () => { const input = { name: "Jane Bear", email: "jane@example.com", - ages: { "Ages 26-45": 2 }, + counts: { adults: 2, youth: 0, kids12: 0, kids9: 0, kids4: 0 }, submissionKey: "sub:412", }; const a = await createTicket(ctx, input); diff --git a/backend/src/ticketService.ts b/backend/src/ticketService.ts index 76fa4dc..f4e03aa 100644 --- a/backend/src/ticketService.ts +++ b/backend/src/ticketService.ts @@ -128,15 +128,19 @@ export async function search(ctx: AppContext, query: string): Promise; // NocoDB age-column title -> count submissionKey: string; } @@ -158,20 +162,29 @@ export async function createTicket( code = generateCode(); } + const c = input.counts; const fields: Record = { [COL.name]: input.name, [COL.email]: input.email, [COL.code]: code, [COL.redeemed]: 0, + [COL.adults]: c.adults, + [COL.youth]: c.youth, + [COL.kids12]: c.kids12, + [COL.kids9]: c.kids9, + [COL.kids4]: c.kids4, [COL.iceTotal]: input.iceBags ?? 0, [COL.iceRedeemed]: 0, [COL.submissionKey]: input.submissionKey, - ...input.ages, }; + if (input.adultNames && input.adultNames.length) fields[COL.adultNames] = input.adultNames.join("\n"); if (input.address !== undefined) fields[COL.address] = input.address; if (input.isDonor !== undefined) fields[COL.isDonor] = input.isDonor; + if (input.donorTier !== undefined) fields[COL.donorTier] = input.donorTier; + if (input.vouchers !== undefined) fields[COL.vouchers] = input.vouchers; if (input.carParking !== undefined) fields[COL.carParking] = input.carParking; if (input.rvParking !== undefined) fields[COL.rvParking] = input.rvParking; + if (input.utv !== undefined) fields[COL.utv] = input.utv; if (input.iceAccess !== undefined) fields[COL.iceAccess] = input.iceAccess; if (input.paymentMethod !== undefined) fields[COL.paymentMethod] = input.paymentMethod; From 4b78c82b35eee5e2c352468e0124cf749b42f4da Mon Sep 17 00:00:00 2001 From: Hank Date: Mon, 13 Jul 2026 03:30:08 +0000 Subject: [PATCH 05/22] Add /crush33 comp-ticket portal + ticket-type badge on scan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Portal (/crush33): password-gated page (PORTAL_PASSWORD) for admins to create entry-only tickets from just name + email, with a category (Guest/Worker/Performer/Volunteer/Speaker). Creates a 1-admission ticket, emails the QR, and shows the QR on-screen. New Ticket Type column. Scanner: shows a prominent TYPE badge (🎭 PERFORMER, 🛠️ WORKER, …) on the confirm + success screens and in admin, so staff can see it's a special ticket. Added Worker + Performer personas to /test. Co-Authored-By: Claude Fable 5 --- app/app/admin.tsx | 1 + app/app/index.tsx | 29 ++++++ app/lib/api.ts | 1 + backend/src/config.ts | 2 + backend/src/fields.ts | 3 + backend/src/routes/portal.ts | 170 +++++++++++++++++++++++++++++++++++ backend/src/routes/test.ts | 20 +++++ backend/src/server.ts | 2 + backend/src/ticketService.ts | 2 + 9 files changed, 230 insertions(+) create mode 100644 backend/src/routes/portal.ts diff --git a/app/app/admin.tsx b/app/app/admin.tsx index f492fc9..e978059 100644 --- a/app/app/admin.tsx +++ b/app/app/admin.tsx @@ -202,6 +202,7 @@ function TicketCard({ ticket, onAdjust }: { ticket: TicketView; onAdjust: (t: Ti const tags: string[] = []; const e = ticket.extras; + if (ticket.ticketType) tags.push(`🎫 ${ticket.ticketType}`); if (e.donorTier === "member") tags.push("🐻 Member"); else if (e.isDonor) tags.push("⭐ Donor"); if (e.carParking) tags.push("🚗 Car"); diff --git a/app/app/index.tsx b/app/app/index.tsx index 297e1d9..ab552ff 100644 --- a/app/app/index.tsx +++ b/app/app/index.tsx @@ -242,6 +242,7 @@ export default function ScannerScreen() { {phase === "success" && ticket && ( + {isIce ? ( <> @@ -366,6 +367,25 @@ function ExtrasRow({ ticket }: { ticket: TicketView }) { ); } +const TYPE_ICON: Record = { + Guest: "🎫", + Worker: "🛠️", + Performer: "🎭", + Volunteer: "🙌", + Speaker: "🎤", +}; + +function TypeBadge({ type }: { type: string }) { + if (!type) return null; + return ( + + + {(TYPE_ICON[type] ?? "🎫") + " " + type.toUpperCase()} + + + ); +} + function AdultNames({ names }: { names: string[] }) { if (!names.length) return null; return ( @@ -405,6 +425,7 @@ function ConfirmCard({ return ( {ticket.name} + {ticket.code} {remaining} of {total} {unit} remaining @@ -507,6 +528,14 @@ const styles = StyleSheet.create({ donorFigureDivider: { width: 1, alignSelf: "stretch", backgroundColor: "rgba(255,255,255,0.35)", marginVertical: 8 }, donorEmail: { color: "rgba(255,255,255,0.85)", fontSize: 14, marginTop: 18 }, + typeBadge: { + backgroundColor: "rgba(255,255,255,0.22)", + borderRadius: 999, + paddingHorizontal: 18, + paddingVertical: 8, + marginTop: 10, + }, + typeBadgeText: { color: "#fff", fontSize: 20, fontWeight: "900", letterSpacing: 1 }, namesBox: { marginTop: 12, alignItems: "center", gap: 3 }, nameLine: { color: "#fff", fontSize: 18, fontWeight: "600", textAlign: "center" }, tags: { flexDirection: "row", flexWrap: "wrap", justifyContent: "center", gap: 8, marginTop: 14 }, diff --git a/app/lib/api.ts b/app/lib/api.ts index 84dd309..2123da8 100644 --- a/app/lib/api.ts +++ b/app/lib/api.ts @@ -21,6 +21,7 @@ export interface TicketView { code: string; name: string; email: string; + ticketType: string; total: number; redeemed: number; remaining: number; diff --git a/backend/src/config.ts b/backend/src/config.ts index df123e5..ef9f7f5 100644 --- a/backend/src/config.ts +++ b/backend/src/config.ts @@ -48,6 +48,8 @@ const schema = z.object({ WEBHOOK_SECRET: z.string().min(1), EVENT_PIN: z.string().min(1), + // Shared password for the /crush33 comp-ticket portal (workers/guests). + PORTAL_PASSWORD: z.string().optional(), TOKEN_SECRET: z.string().min(16), TOKEN_TTL: z.string().default("30d"), diff --git a/backend/src/fields.ts b/backend/src/fields.ts index 5c669e8..c6b4cc8 100644 --- a/backend/src/fields.ts +++ b/backend/src/fields.ts @@ -24,6 +24,7 @@ export const COL = { utv: "UTV", iceAccess: "Ice Access", paymentMethod: "Payment Method", + ticketType: "Ticket Type", // "" for regular; Guest/Worker/Performer/Volunteer/Speaker for portal comps // Columns this system manages: code: "Ticket Code", @@ -94,6 +95,7 @@ export interface TicketView { code: string; name: string; email: string; + ticketType: string; // "" for regular; Guest/Worker/... for special tickets total: number; redeemed: number; remaining: number; @@ -121,6 +123,7 @@ export function toView(rec: NocoRecord): TicketView { code: String(rec[COL.code] ?? ""), name: String(rec[COL.name] ?? ""), email: String(rec[COL.email] ?? ""), + ticketType: String(rec[COL.ticketType] ?? ""), total, redeemed, remaining: Math.max(0, total - redeemed), diff --git a/backend/src/routes/portal.ts b/backend/src/routes/portal.ts new file mode 100644 index 0000000..9a1f077 --- /dev/null +++ b/backend/src/routes/portal.ts @@ -0,0 +1,170 @@ +import { timingSafeEqual } from "node:crypto"; +import type { FastifyInstance } from "fastify"; +import { createTicket } from "../ticketService.js"; +import { renderQrPng, renderQrDataUrl } from "../services/qrcode.js"; + +const TYPES = ["Guest", "Worker", "Performer", "Volunteer", "Speaker"]; + +function safeEqual(a: string, b: string): boolean { + const ba = Buffer.from(a || ""); + const bb = Buffer.from(b || ""); + if (ba.length !== bb.length) return false; + return timingSafeEqual(ba, bb); +} + +/** + * /crush33 — password-gated comp-ticket portal for admins. Creates entry-only + * tickets (1 admission, no demographics/ice) with a category (Guest/Worker/…) + * that shows on the scanner. Password checked server-side per request. + */ +export async function portalRoutes(app: FastifyInstance): Promise { + app.get("/crush33", async (_req, reply) => { + reply.type("text/html").send(PAGE); + }); + + app.post( + "/api/portal/create-ticket", + { config: { rateLimit: { max: 20, timeWindow: "1 minute" } } }, + async (req, reply) => { + const cfg = app.ctx.config; + if (!cfg.PORTAL_PASSWORD) return reply.code(404).send({ error: "portal_disabled" }); + + const b = (req.body ?? {}) as { password?: string; name?: string; email?: string; type?: string }; + if (!b.password || !safeEqual(b.password, cfg.PORTAL_PASSWORD)) { + return reply.code(401).send({ error: "bad_password" }); + } + const name = String(b.name ?? "").trim(); + const email = String(b.email ?? "").trim(); + const type = TYPES.includes(String(b.type)) ? String(b.type) : "Guest"; + if (!name || !email) { + return reply.code(400).send({ error: "missing_fields", detail: "name and email are required" }); + } + + let result: Awaited>; + try { + result = await createTicket(app.ctx, { + name, + adultNames: [name], + email, + ticketType: type, + counts: { adults: 1, youth: 0, kids12: 0, kids9: 0, kids4: 0 }, + submissionKey: `portal:${Date.now()}:${Math.trunc(Math.random() * 1e9)}`, + }); + } catch (e: any) { + req.log.error({ err: e }, "portal: create failed"); + return reply.code(502).send({ error: "db_error", detail: e?.message }); + } + + // Email the QR (best-effort — the portal also shows it on-screen). + let emailSent = false; + if (!app.ctx.mailer.isBlockedRecipient(email)) { + try { + const png = await renderQrPng(result.code); + await app.ctx.mailer.sendTicket({ toEmail: email, toName: name, code: result.code, quantity: 1, qrPng: png }); + emailSent = true; + } catch (e: any) { + req.log.error({ err: e, code: result.code }, "portal: email failed"); + } + } + + const qr = await renderQrDataUrl(result.code); + return { ok: true, code: result.code, type, name, emailSent, qr }; + }, + ); +} + +const PAGE = ` + + + + + +Camp Scan — Comp Tickets + + + +
+
+ +

Comp Ticket Portal

+

Entry-only tickets for workers & guests

+
+ + + + + + + + + + + + + + +
+ +
+ Ticket QR +
+
+
+ +
+
+ + + +`; diff --git a/backend/src/routes/test.ts b/backend/src/routes/test.ts index 4118f79..1096416 100644 --- a/backend/src/routes/test.ts +++ b/backend/src/routes/test.ts @@ -15,6 +15,7 @@ interface Persona { utv?: boolean; isDonor?: boolean; donorTier?: string; + ticketType?: string; exhaust?: boolean; // pre-redeem all tickets so it scans as "exhausted" blurb: string; } @@ -72,6 +73,24 @@ const PERSONAS: Persona[] = [ exhaust: true, blurb: "2 tickets, already fully redeemed. Check-in mode → red 'exhausted'.", }, + { + key: "worker", + name: "Wanda Worker", + email: "worker@test.beartaria", + adultNames: ["Wanda Worker"], + counts: C(1), + ticketType: "Worker", + blurb: "Entry-only WORKER comp ticket. Check-in mode → green with a Worker badge.", + }, + { + key: "performer", + name: "Perry Performer", + email: "performer@test.beartaria", + adultNames: ["Perry Performer"], + counts: C(1), + ticketType: "Performer", + blurb: "Entry-only PERFORMER comp ticket. Check-in mode → green with a Performer badge.", + }, ]; const INVALID_CODE = "BC26-0000-0000"; // not in the DB → scans as "not found" @@ -94,6 +113,7 @@ export async function testRoutes(app: FastifyInstance): Promise { utv: p.utv, isDonor: p.isDonor, donorTier: p.donorTier, + ticketType: p.ticketType, submissionKey: `test:${p.key}`, }); // Keep the "exhausted" persona fully redeemed on every load so its state diff --git a/backend/src/server.ts b/backend/src/server.ts index 79fba69..b10433e 100644 --- a/backend/src/server.ts +++ b/backend/src/server.ts @@ -14,6 +14,7 @@ import { testRoutes } from "./routes/test.js"; import { installRoutes } from "./routes/install.js"; import { webhookDocRoutes } from "./routes/webhookDoc.js"; import { publicLookupRoutes } from "./routes/publicLookup.js"; +import { portalRoutes } from "./routes/portal.js"; export async function build() { const config = loadConfig(); @@ -36,6 +37,7 @@ export async function build() { await app.register(installRoutes); await app.register(webhookDocRoutes); await app.register(publicLookupRoutes); + await app.register(portalRoutes); // Serve the exported Expo web build (if present) with SPA fallback. const webDir = config.WEB_DIR ?? join(process.cwd(), "web"); diff --git a/backend/src/ticketService.ts b/backend/src/ticketService.ts index f4e03aa..c894f76 100644 --- a/backend/src/ticketService.ts +++ b/backend/src/ticketService.ts @@ -130,6 +130,7 @@ export interface WebhookInput { name: string; adultNames?: string[]; email: string; + ticketType?: string; // Guest/Worker/Performer/Volunteer/Speaker for portal comps address?: string; isDonor?: boolean; donorTier?: string; @@ -178,6 +179,7 @@ export async function createTicket( [COL.submissionKey]: input.submissionKey, }; if (input.adultNames && input.adultNames.length) fields[COL.adultNames] = input.adultNames.join("\n"); + if (input.ticketType) fields[COL.ticketType] = input.ticketType; if (input.address !== undefined) fields[COL.address] = input.address; if (input.isDonor !== undefined) fields[COL.isDonor] = input.isDonor; if (input.donorTier !== undefined) fields[COL.donorTier] = input.donorTier; From 848c8c7ee83e2cea75765a1df5bd33973cea31eb Mon Sep 17 00:00:00 2001 From: Hank Date: Mon, 13 Jul 2026 03:53:44 +0000 Subject: [PATCH 06/22] compose: read env from backend/.env (single source of truth) Was ./.env, which required a manual copy from backend/.env and could go stale (e.g. a changed PORTAL_PASSWORD not taking effect). Point env_file straight at backend/.env so there's one file to edit. Co-Authored-By: Claude Fable 5 --- docker-compose.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 20e1aa0..3668405 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,9 @@ services: build: . image: camptickets:latest container_name: camptickets - env_file: .env + # Single source of truth for secrets — edit backend/.env, then + # `docker compose up -d`. (Was ./.env; consolidated to avoid a stale copy.) + env_file: backend/.env environment: # Container always listens on 8080 internally; the host mapping below is # what nginx proxies to. Keep this fixed regardless of .env PORT. From 251edfce42cd63083a038dafa7c64019e2e13c95 Mon Sep 17 00:00:00 2001 From: Hank Date: Mon, 13 Jul 2026 05:54:36 +0000 Subject: [PATCH 07/22] CI: upload APK to the Forgejo release via API instead of forgejo-release action MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The build succeeds but publishing failed with "$FORGEJO_PATH: ambiguous redirect" — the moving actions/forgejo-release@v2 tag updated to a broken version. Replace it with direct Forgejo API calls (create release, delete any prior same-named asset, upload the APK) using the built-in token, so the last step is under our control. Co-Authored-By: Claude Fable 5 --- .forgejo/workflows/build-apk.yml | 38 +++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/.forgejo/workflows/build-apk.yml b/.forgejo/workflows/build-apk.yml index 3f3fd2b..2564239 100644 --- a/.forgejo/workflows/build-apk.yml +++ b/.forgejo/workflows/build-apk.yml @@ -139,14 +139,30 @@ jobs: cp app/build/outputs/apk/release/app-release.apk \ "$GITHUB_WORKSPACE/artifacts/camp-scan-${{ steps.ver.outputs.tag }}.apk" - - name: Publish Forgejo release with APK - uses: actions/forgejo-release@v2 - with: - direction: upload - url: https://git.mowden.top - repo: Beartaria/CampgroundTickets - tag: ${{ steps.ver.outputs.tag }} - token: ${{ secrets.GITHUB_TOKEN }} - release-dir: artifacts - release-notes: "Camp Scan ${{ steps.ver.outputs.tag }} — install/update via Obtainium." - override: true + - name: Publish APK to Forgejo release + env: + TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG: ${{ steps.ver.outputs.tag }} + run: | + set -eu + API="https://git.mowden.top/api/v1/repos/Beartaria/CampgroundTickets" + APK="$GITHUB_WORKSPACE/artifacts/camp-scan-${TAG}.apk" + AUTH="Authorization: token ${TOKEN}" + # Create the release for this tag (ignore failure if it already exists). + curl -sS -X POST "$API/releases" -H "$AUTH" -H "Content-Type: application/json" \ + -d "{\"tag_name\":\"${TAG}\",\"name\":\"Camp Scan ${TAG}\",\"body\":\"Install/update via Obtainium.\"}" \ + -o /dev/null -w "create release: %{http_code}\n" || true + # Look up the release id by tag. + REL_ID=$(curl -sS "$API/releases/tags/${TAG}" -H "$AUTH" | grep -o '"id":[0-9]*' | head -1 | grep -o '[0-9]*') + echo "release id: ${REL_ID}" + test -n "$REL_ID" + # Remove a same-named asset from a prior run, then upload the APK. + EXISTING=$(curl -sS "$API/releases/${REL_ID}/assets" -H "$AUTH" \ + | tr '}' '\n' | grep -F "camp-scan-${TAG}.apk" | grep -o '"id":[0-9]*' | head -1 | grep -o '[0-9]*' || true) + if [ -n "${EXISTING:-}" ]; then + curl -sS -X DELETE "$API/releases/${REL_ID}/assets/${EXISTING}" -H "$AUTH" -o /dev/null -w "delete old asset: %{http_code}\n" + fi + curl -sS -f -X POST "$API/releases/${REL_ID}/assets?name=camp-scan-${TAG}.apk" \ + -H "$AUTH" -F "attachment=@${APK};type=application/vnd.android.package-archive" \ + -o /dev/null -w "upload apk: %{http_code}\n" + echo "Published camp-scan-${TAG}.apk" From 43fddec2862938ebfe602d4adf18d8ef2cbb845c Mon Sep 17 00:00:00 2001 From: Hank Date: Mon, 13 Jul 2026 17:30:18 +0000 Subject: [PATCH 08/22] Add event report dashboard, slide-out drawer, in-app comp portal + creator tracking - Reporting: GET /api/stats aggregates check-in progress, ice, ticket types, people breakdown, add-ons/donors, gate-crew leaderboard (from audit), comp tickets by creator, and a by-hour check-in timeline. New /stats screen. - Slide-out drawer (custom RN Animated, no new native deps) replaces per-screen header links; available on every main screen via a hamburger. - In-app comp portal (/comp), password-gated like /crush33, reusing the portal endpoints; records the issuing gate-staff name (Created By column) and reports comps per creator. Co-Authored-By: Claude Fable 5 --- app/app/_layout.tsx | 5 +- app/app/admin.tsx | 9 +- app/app/comp.tsx | 239 +++++++++++++++++++++++++ app/app/index.tsx | 24 +-- app/app/stats.tsx | 306 +++++++++++++++++++++++++++++++++ app/components/SideMenu.tsx | 112 ++++++++++++ app/lib/api.ts | 58 +++++++ app/lib/menu.tsx | 21 +++ backend/src/fields.ts | 3 + backend/src/routes/portal.ts | 26 ++- backend/src/routes/tickets.ts | 7 + backend/src/services/audit.ts | 37 ++++ backend/src/services/nocodb.ts | 20 +++ backend/src/services/stats.ts | 131 ++++++++++++++ backend/src/ticketService.ts | 2 + 15 files changed, 979 insertions(+), 21 deletions(-) create mode 100644 app/app/comp.tsx create mode 100644 app/app/stats.tsx create mode 100644 app/components/SideMenu.tsx create mode 100644 app/lib/menu.tsx create mode 100644 backend/src/services/stats.ts diff --git a/app/app/_layout.tsx b/app/app/_layout.tsx index 358a7a4..cfd2a76 100644 --- a/app/app/_layout.tsx +++ b/app/app/_layout.tsx @@ -4,6 +4,7 @@ import { Stack, useRouter, useSegments } from "expo-router"; import { SafeAreaProvider } from "react-native-safe-area-context"; import { StatusBar } from "expo-status-bar"; import { AuthProvider, useAuth } from "../lib/auth"; +import { MenuProvider } from "../lib/menu"; import { theme } from "../lib/theme"; export default function RootLayout() { @@ -11,7 +12,9 @@ export default function RootLayout() { - + + + ); diff --git a/app/app/admin.tsx b/app/app/admin.tsx index e978059..92b4052 100644 --- a/app/app/admin.tsx +++ b/app/app/admin.tsx @@ -4,6 +4,7 @@ import { router } from "expo-router"; import { SafeAreaView } from "react-native-safe-area-context"; import { searchTickets, redeem, getAudit, type TicketView, type AuditEntry } from "../lib/api"; import { feedbackSuccess, feedbackError } from "../lib/feedback"; +import { useMenu } from "../lib/menu"; import { theme } from "../lib/theme"; function fmtTime(iso: string): string { @@ -43,6 +44,7 @@ function AuditList({ entries }: { entries: AuditEntry[] }) { } export default function AdminScreen() { + const { open: openMenu } = useMenu(); const [q, setQ] = useState(""); const [results, setResults] = useState([]); const [busy, setBusy] = useState(false); @@ -119,10 +121,8 @@ export default function AdminScreen() { return ( - router.replace("/")} hitSlop={10}> - - ‹ Scanner - + + Admin lookup @@ -276,6 +276,7 @@ const styles = StyleSheet.create({ paddingVertical: 10, }, brand: { color: theme.text, fontSize: 18, fontWeight: "700" }, + hamburger: { color: theme.text, fontSize: 26, fontWeight: "700" }, link: { color: theme.textDim, fontSize: 16, fontWeight: "600" }, searchRow: { flexDirection: "row", gap: 10, paddingHorizontal: 16, marginTop: 6 }, input: { diff --git a/app/app/comp.tsx b/app/app/comp.tsx new file mode 100644 index 0000000..364aac0 --- /dev/null +++ b/app/app/comp.tsx @@ -0,0 +1,239 @@ +import { useState } from "react"; +import { + StyleSheet, + View, + Text, + TextInput, + Pressable, + ScrollView, + Image, + KeyboardAvoidingView, + Platform, +} from "react-native"; +import { router } from "expo-router"; +import { SafeAreaView } from "react-native-safe-area-context"; +import { portalVerify, portalCreate, AuthError, type PortalTicket } from "../lib/api"; +import { useAuth } from "../lib/auth"; +import { useMenu } from "../lib/menu"; +import { theme } from "../lib/theme"; + +const TYPES = ["Guest", "Worker", "Performer", "Volunteer", "Speaker"]; +const TYPE_ICON: Record = { + Guest: "🎫", + Worker: "🛠️", + Performer: "🎭", + Volunteer: "🙌", + Speaker: "🎤", +}; + +export default function CompScreen() { + const { operator } = useAuth(); + const { open: openMenu } = useMenu(); + const [password, setPassword] = useState(""); + const [unlocked, setUnlocked] = useState(false); + const [busy, setBusy] = useState(false); + const [error, setError] = useState(""); + + const [type, setType] = useState("Guest"); + const [name, setName] = useState(""); + const [email, setEmail] = useState(""); + const [result, setResult] = useState(null); + + async function unlock() { + if (!password || busy) return; + setBusy(true); + setError(""); + try { + await portalVerify(password); + setUnlocked(true); + } catch (e: any) { + setError(e instanceof AuthError ? "Wrong password" : (e?.message ?? "Failed")); + } finally { + setBusy(false); + } + } + + async function create() { + if (!name.trim() || !email.trim() || busy) return; + setBusy(true); + setError(""); + try { + const r = await portalCreate({ password, name: name.trim(), email: email.trim(), type, createdBy: operator }); + setResult(r); + setName(""); + setEmail(""); + } catch (e: any) { + if (e instanceof AuthError) { + setUnlocked(false); // password rotated — re-gate + setError("Password changed — unlock again."); + } else { + setError(e?.message ?? "Failed to create ticket"); + } + } finally { + setBusy(false); + } + } + + return ( + + + + + + Comp Tickets + + + + + + {!unlocked ? ( + + Entry-only tickets for workers & guests. Enter the shared portal password. + Portal password + + {!!error && {error}} + + {busy ? "Checking…" : "Unlock"} + + + ) : ( + + Ticket type + + {TYPES.map((t) => ( + setType(t)} + > + + {(TYPE_ICON[t] ?? "🎫") + " " + t} + + + ))} + + + Full name + + + Email + + + {!!error && {error}} + + {busy ? "Creating…" : `Create ${type} ticket`} + + + {result && ( + + + {result.code} + + {result.type} · {result.name} + + + {result.emailSent ? "✓ Emailed the ticket" : "Email not sent — screenshot this QR"} + + + )} + + )} + + + + ); +} + +const styles = StyleSheet.create({ + root: { flex: 1, backgroundColor: theme.bg }, + topbar: { + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between", + paddingHorizontal: 16, + paddingVertical: 10, + }, + brand: { color: theme.text, fontSize: 18, fontWeight: "700" }, + hamburger: { color: theme.text, fontSize: 26, fontWeight: "700" }, + link: { color: theme.textDim, fontSize: 16, fontWeight: "600", width: 72 }, + lead: { color: theme.textDim, fontSize: 15, lineHeight: 21, marginBottom: 8 }, + label: { color: theme.textDim, fontSize: 13, marginTop: 16, marginBottom: 6 }, + input: { + backgroundColor: theme.card, + borderWidth: 1, + borderColor: theme.cardBorder, + borderRadius: 12, + paddingHorizontal: 14, + paddingVertical: 14, + color: theme.text, + fontSize: 16, + }, + error: { color: theme.dangerBright, marginTop: 12, fontSize: 14, fontWeight: "600" }, + btn: { + backgroundColor: theme.successBright, + borderRadius: 13, + paddingVertical: 15, + alignItems: "center", + marginTop: 20, + }, + btnOff: { opacity: 0.4 }, + btnText: { color: "#06210f", fontSize: 18, fontWeight: "800" }, + + types: { flexDirection: "row", flexWrap: "wrap", gap: 8 }, + typePill: { + backgroundColor: theme.card, + borderWidth: 1, + borderColor: theme.cardBorder, + borderRadius: 999, + paddingHorizontal: 14, + paddingVertical: 9, + }, + typePillOn: { backgroundColor: theme.primary, borderColor: theme.primary }, + typePillText: { color: theme.textDim, fontSize: 14, fontWeight: "700" }, + typePillTextOn: { color: "#fff" }, + + result: { + marginTop: 22, + alignItems: "center", + backgroundColor: theme.card, + borderWidth: 1, + borderColor: theme.cardBorder, + borderRadius: 16, + padding: 20, + }, + qr: { width: 220, height: 220, backgroundColor: "#fff", borderRadius: 10 }, + rcode: { color: theme.successBright, fontSize: 22, fontWeight: "800", letterSpacing: 2, marginTop: 12 }, + rwho: { color: theme.text, fontSize: 16, marginTop: 4 }, + rmail: { color: theme.textDim, fontSize: 13, marginTop: 8 }, +}); diff --git a/app/app/index.tsx b/app/app/index.tsx index ab552ff..c3bcdbc 100644 --- a/app/app/index.tsx +++ b/app/app/index.tsx @@ -6,6 +6,7 @@ import QRScanner from "../components/QRScanner"; import ResultOverlay from "../components/ResultOverlay"; import { lookup, redeem, banquet, type TicketView, type DonorLookup } from "../lib/api"; import { useAuth } from "../lib/auth"; +import { useMenu } from "../lib/menu"; import { feedbackSuccess, feedbackError } from "../lib/feedback"; import { theme } from "../lib/theme"; @@ -19,7 +20,8 @@ const MODES: { key: Mode; label: string; icon: string }[] = [ ]; export default function ScannerScreen() { - const { signOut, operator } = useAuth(); + const { operator } = useAuth(); + const { open: openMenu } = useMenu(); const [mode, setMode] = useState("tickets"); const [phase, setPhase] = useState("scanning"); const [ticket, setTicket] = useState(null); @@ -147,29 +149,19 @@ export default function ScannerScreen() { } }, [ticket, count, mode, resume, showError]); - const doLogout = useCallback(async () => { - await signOut(); - // The auth gate redirects to /login when signedIn flips to false. - }, [signOut]); - const isIce = mode === "ice"; const successNoun = isIce ? (checkedIn === 1 ? "bag of ice" : "bags of ice") : ""; return ( - + + + + 🐻 Camp Scan {!!operator && {operator}} - - router.push("/admin")} hitSlop={10}> - Admin - - - Sign out - - @@ -474,6 +466,8 @@ const styles = StyleSheet.create({ paddingHorizontal: 16, paddingVertical: 10, }, + hamburger: { color: theme.text, fontSize: 26, fontWeight: "700", paddingRight: 4 }, + titleWrap: { flex: 1, marginLeft: 12 }, brand: { color: theme.text, fontSize: 18, fontWeight: "700" }, operator: { color: theme.textDim, fontSize: 13, marginTop: 1 }, topActions: { flexDirection: "row", gap: 18, alignItems: "center" }, diff --git a/app/app/stats.tsx b/app/app/stats.tsx new file mode 100644 index 0000000..9c9428a --- /dev/null +++ b/app/app/stats.tsx @@ -0,0 +1,306 @@ +import { useCallback, useEffect, useState } from "react"; +import { StyleSheet, View, Text, Pressable, ScrollView, ActivityIndicator, RefreshControl } from "react-native"; +import { router } from "expo-router"; +import { SafeAreaView } from "react-native-safe-area-context"; +import { getStats, type Stats } from "../lib/api"; +import { useMenu } from "../lib/menu"; +import { theme } from "../lib/theme"; + +const TYPE_ICON: Record = { + Regular: "🎟️", + Guest: "🎫", + Worker: "🛠️", + Performer: "🎭", + Volunteer: "🙌", + Speaker: "🎤", +}; +const MEDAL = ["🥇", "🥈", "🥉"]; + +function Bar({ pct, color }: { pct: number; color?: string }) { + return ( + + + + ); +} + +function Tile({ value, label, accent }: { value: string | number; label: string; accent?: boolean }) { + return ( + + {value} + {label} + + ); +} + +export default function StatsScreen() { + const { open: openMenu } = useMenu(); + const [stats, setStats] = useState(null); + const [loading, setLoading] = useState(true); + const [refreshing, setRefreshing] = useState(false); + const [error, setError] = useState(""); + + const load = useCallback(async (force = false) => { + setError(""); + try { + setStats(await getStats(force)); + } catch (e: any) { + if (e?.name === "AuthError") return router.replace("/login"); + setError(e?.message ?? "Failed to load report"); + } finally { + setLoading(false); + setRefreshing(false); + } + }, []); + + useEffect(() => { + load(); + }, [load]); + + const onRefresh = () => { + setRefreshing(true); + load(true); + }; + + const peakHour = stats?.checkinsByHour.length + ? stats.checkinsByHour.reduce((a, b) => (b.count > a.count ? b : a)) + : null; + const maxHour = stats ? Math.max(1, ...stats.checkinsByHour.map((h) => h.count)) : 1; + + return ( + + + + + + Event Report + + + + + + {loading ? ( + + ) : error ? ( + {error} + ) : stats ? ( + } + > + {/* Hero: check-in progress */} + + {stats.tickets.pct}% + checked in + + + {stats.tickets.redeemed} of {stats.tickets.total} tickets · {stats.tickets.remaining} to go + + + + {/* Core tiles */} + + + + + + + + {/* Ice */} + + 🧊 Ice + + + {stats.ice.redeemed} of {stats.ice.total} bags handed out · {stats.ice.remaining} left · {stats.ice.ticketsSold} ice tickets sold + + + + {/* Ticket types */} + + Ticket types + {stats.types.map((t) => ( + + + {(TYPE_ICON[t.type] ?? "🎫") + " " + t.type} + + + + + + {t.redeemed}/{t.total} + · {t.count}× + + + ))} + + + {/* People breakdown */} + + Who's coming + + + + + + + + + {/* Extras + donors */} + + Add-ons & donors + + 🚗 {stats.extras.carParking} parking + 🚐 {stats.extras.rvParking} RV + 🏍️ {stats.extras.utv} UTV + 🐻 {stats.donors.members} members + ⭐ {stats.donors.orders} donor orders + 🎟️ {stats.donors.vouchers} vouchers + + + + {/* Operator leaderboard */} + {stats.operators.length > 0 && ( + + Gate crew leaderboard + {stats.operators.slice(0, 8).map((o, i) => ( + + {MEDAL[i] ?? `${i + 1}.`} + + {o.name} + + + {o.checkins} check-ins{o.ice ? ` · ${o.ice} ice` : ""} + {o.undos ? ` · ${o.undos} undo` : ""} + + + ))} + + )} + + {/* Comp tickets issued */} + {stats.comps.total > 0 && ( + + 🎟️ Comp tickets issued ({stats.comps.total}) + {stats.comps.byCreator.map((c) => ( + + + {c.name} + + {c.count} issued + + ))} + + )} + + {/* Check-in timeline */} + {stats.checkinsByHour.length > 0 && ( + + Check-ins by hour + + {stats.checkinsByHour.map((h) => ( + + {h.count} + + {h.hour.slice(11)}h + + ))} + + {peakHour && ( + Busiest hour: {peakHour.count} checked in around {peakHour.hour.slice(11)}:00 + )} + + )} + + Updated {new Date(stats.generatedAt).toLocaleTimeString()} · pull to refresh + + ) : null} + + ); +} + +const styles = StyleSheet.create({ + root: { flex: 1, backgroundColor: theme.bg }, + topbar: { + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between", + paddingHorizontal: 16, + paddingVertical: 10, + }, + brand: { color: theme.text, fontSize: 18, fontWeight: "700" }, + hamburger: { color: theme.text, fontSize: 26, fontWeight: "700" }, + link: { color: theme.textDim, fontSize: 16, fontWeight: "700" }, + error: { color: theme.dangerBright, textAlign: "center", marginTop: 40, fontSize: 15 }, + + hero: { + backgroundColor: theme.card, + borderWidth: 1, + borderColor: theme.cardBorder, + borderRadius: 18, + padding: 22, + alignItems: "center", + }, + heroPct: { color: theme.successBright, fontSize: 64, fontWeight: "900", lineHeight: 66 }, + heroSub: { color: theme.textDim, fontSize: 15, marginBottom: 14 }, + heroCounts: { color: theme.text, fontSize: 15, marginTop: 10, textAlign: "center" }, + + barTrack: { width: "100%", height: 12, borderRadius: 6, backgroundColor: theme.cardBorder, overflow: "hidden" }, + barFill: { height: "100%", borderRadius: 6 }, + + tileRow: { flexDirection: "row", flexWrap: "wrap", gap: 10, marginTop: 12 }, + tile: { + flexGrow: 1, + flexBasis: "22%", + minWidth: 74, + backgroundColor: theme.card, + borderWidth: 1, + borderColor: theme.cardBorder, + borderRadius: 12, + paddingVertical: 12, + alignItems: "center", + }, + tileValue: { color: theme.text, fontSize: 24, fontWeight: "800" }, + tileLabel: { color: theme.textDim, fontSize: 11, marginTop: 2, textAlign: "center" }, + + card: { + backgroundColor: theme.card, + borderWidth: 1, + borderColor: theme.cardBorder, + borderRadius: 16, + padding: 16, + marginTop: 14, + }, + cardTitle: { color: theme.text, fontSize: 16, fontWeight: "800", marginBottom: 10 }, + cardSub: { color: theme.textDim, fontSize: 13, marginTop: 8, lineHeight: 18 }, + + typeRow: { flexDirection: "row", alignItems: "center", gap: 10, marginVertical: 5 }, + typeName: { color: theme.text, fontSize: 14, fontWeight: "600", width: 120 }, + typeBarWrap: { flex: 1 }, + typeCount: { color: theme.text, fontSize: 13, fontWeight: "700", minWidth: 66, textAlign: "right" }, + typeOrders: { color: theme.textDim, fontWeight: "400" }, + + chips: { flexDirection: "row", flexWrap: "wrap", gap: 8 }, + chip: { + color: theme.text, + backgroundColor: theme.cardBorder, + borderRadius: 999, + paddingHorizontal: 12, + paddingVertical: 7, + fontSize: 13, + fontWeight: "600", + overflow: "hidden", + }, + + opRow: { flexDirection: "row", alignItems: "center", gap: 10, paddingVertical: 6 }, + opRank: { fontSize: 16, width: 28, textAlign: "center", color: theme.textDim, fontWeight: "800" }, + opName: { color: theme.text, fontSize: 15, fontWeight: "600", flex: 1 }, + opStat: { color: theme.textDim, fontSize: 13 }, + + spark: { flexDirection: "row", alignItems: "flex-end", justifyContent: "space-between", gap: 4, height: 118, marginTop: 4 }, + sparkCol: { flex: 1, alignItems: "center", justifyContent: "flex-end" }, + sparkVal: { color: theme.textDim, fontSize: 10, marginBottom: 3 }, + sparkBar: { width: "70%", minWidth: 8, backgroundColor: theme.successBright, borderRadius: 3 }, + sparkLabel: { color: theme.textDim, fontSize: 9, marginTop: 3 }, + + stamp: { color: theme.textDim, fontSize: 12, textAlign: "center", marginTop: 20 }, +}); diff --git a/app/components/SideMenu.tsx b/app/components/SideMenu.tsx new file mode 100644 index 0000000..522b2c3 --- /dev/null +++ b/app/components/SideMenu.tsx @@ -0,0 +1,112 @@ +import { useEffect, useRef } from "react"; +import { Animated, StyleSheet, View, Text, Pressable, Easing, useWindowDimensions } from "react-native"; +import { router, useSegments } from "expo-router"; +import { useAuth } from "../lib/auth"; +import { theme } from "../lib/theme"; + +const ITEMS: { label: string; icon: string; route: string; seg: string }[] = [ + { label: "Scanner", icon: "📷", route: "/", seg: "" }, + { label: "Event report", icon: "📊", route: "/stats", seg: "stats" }, + { label: "Comp tickets", icon: "🎟️", route: "/comp", seg: "comp" }, + { label: "Admin lookup", icon: "🔎", route: "/admin", seg: "admin" }, +]; + +export default function SideMenu({ visible, onClose }: { visible: boolean; onClose: () => void }) { + const { operator, signOut } = useAuth(); + const segments = useSegments(); + const current = segments[0] ?? ""; + const { width } = useWindowDimensions(); + const panelW = Math.min(320, width * 0.84); + const tx = useRef(new Animated.Value(-panelW)).current; + const fade = useRef(new Animated.Value(0)).current; + + useEffect(() => { + Animated.parallel([ + Animated.timing(tx, { + toValue: visible ? 0 : -panelW, + duration: 220, + easing: Easing.out(Easing.cubic), + useNativeDriver: true, + }), + Animated.timing(fade, { toValue: visible ? 1 : 0, duration: 220, useNativeDriver: true }), + ]).start(); + }, [visible, panelW, tx, fade]); + + const go = (item: { route: string; seg: string }) => { + onClose(); + if (item.seg !== current) router.replace(item.route as any); + }; + + return ( + + + + + + + 🐻 Camp Scan + {!!operator && {operator}} + + + {ITEMS.map((it) => { + const active = it.seg === current; + return ( + go(it)}> + {it.icon} + {it.label} + + ); + })} + + + { + onClose(); + signOut(); + }} + > + 🚪 + Sign out + + + + ); +} + +const styles = StyleSheet.create({ + scrim: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0, backgroundColor: "rgba(0,0,0,0.55)" }, + panel: { + position: "absolute", + top: 0, + bottom: 0, + left: 0, + backgroundColor: theme.card, + borderRightWidth: 1, + borderRightColor: theme.cardBorder, + paddingTop: 54, + paddingHorizontal: 14, + paddingBottom: 28, + }, + header: { paddingHorizontal: 8, paddingBottom: 14, borderBottomWidth: 1, borderBottomColor: theme.cardBorder }, + logo: { color: theme.text, fontSize: 20, fontWeight: "800" }, + operator: { color: theme.textDim, fontSize: 14, marginTop: 3 }, + items: { marginTop: 14, gap: 4 }, + item: { flexDirection: "row", alignItems: "center", gap: 14, paddingVertical: 14, paddingHorizontal: 12, borderRadius: 12 }, + itemActive: { backgroundColor: theme.primary }, + itemIcon: { fontSize: 20, width: 26, textAlign: "center" }, + itemText: { color: theme.text, fontSize: 17, fontWeight: "600" }, + itemTextActive: { color: "#fff", fontWeight: "800" }, + spacer: { flex: 1 }, + signout: { + flexDirection: "row", + alignItems: "center", + gap: 14, + paddingVertical: 14, + paddingHorizontal: 12, + borderRadius: 12, + borderTopWidth: 1, + borderTopColor: theme.cardBorder, + }, + signoutText: { color: theme.dangerBright, fontSize: 17, fontWeight: "700" }, +}); diff --git a/app/lib/api.ts b/app/lib/api.ts index 2123da8..ccc02e8 100644 --- a/app/lib/api.ts +++ b/app/lib/api.ts @@ -22,6 +22,7 @@ export interface TicketView { name: string; email: string; ticketType: string; + createdBy: string; total: number; redeemed: number; remaining: number; @@ -194,6 +195,63 @@ export interface AuditEntry { action: "check-in" | "undo" | "ice" | "ice-undo"; } +export interface Stats { + orders: number; + tickets: { total: number; redeemed: number; remaining: number; pct: number }; + people: { adults: number; youth: number; kids12: number; kids9: number; kids4Free: number }; + ice: { total: number; redeemed: number; remaining: number; pct: number; ticketsSold: number }; + types: { type: string; count: number; total: number; redeemed: number }[]; + donors: { orders: number; members: number; vouchers: number }; + extras: { carParking: number; rvParking: number; utv: number }; + comps: { total: number; byCreator: { name: string; count: number }[] }; + operators: { name: string; checkins: number; ice: number; undos: number }[]; + checkinsByHour: { hour: string; count: number }[]; + generatedAt: string; +} + +export function getStats(force = false): Promise { + return authed(`/api/stats${force ? "?force=1" : ""}`); +} + +// Comp-ticket portal (password-gated; separate from the staff PIN). +export async function portalVerify(password: string): Promise<{ ok: boolean; types: string[] }> { + const res = await fetch(`${API_BASE}/api/portal/verify`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ password }), + }); + if (res.status === 401) throw new AuthError("Wrong password"); + if (!res.ok) throw new ApiError(`Verify failed (${res.status})`); + return res.json(); +} + +export interface PortalTicket { + ok: boolean; + code: string; + type: string; + name: string; + emailSent: boolean; + qr: string; // data URL +} + +export async function portalCreate(input: { + password: string; + name: string; + email: string; + type: string; + createdBy?: string; +}): Promise { + const res = await fetch(`${API_BASE}/api/portal/create-ticket`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(input), + }); + if (res.status === 401) throw new AuthError("Wrong password"); + const body = await res.json().catch(() => ({})); + if (!res.ok) throw new ApiError(body?.detail ?? body?.error ?? `Create failed (${res.status})`); + return body; +} + export function getAudit(opts: { code?: string; limit?: number } = {}): Promise<{ enabled: boolean; entries: AuditEntry[]; diff --git a/app/lib/menu.tsx b/app/lib/menu.tsx new file mode 100644 index 0000000..356c944 --- /dev/null +++ b/app/lib/menu.tsx @@ -0,0 +1,21 @@ +import { createContext, useContext, useState, type ReactNode } from "react"; +import SideMenu from "../components/SideMenu"; + +interface MenuState { + open: () => void; + close: () => void; +} + +const Ctx = createContext({ open: () => {}, close: () => {} }); + +export function MenuProvider({ children }: { children: ReactNode }) { + const [visible, setVisible] = useState(false); + return ( + setVisible(true), close: () => setVisible(false) }}> + {children} + setVisible(false)} /> + + ); +} + +export const useMenu = () => useContext(Ctx); diff --git a/backend/src/fields.ts b/backend/src/fields.ts index c6b4cc8..50c569d 100644 --- a/backend/src/fields.ts +++ b/backend/src/fields.ts @@ -25,6 +25,7 @@ export const COL = { iceAccess: "Ice Access", paymentMethod: "Payment Method", ticketType: "Ticket Type", // "" for regular; Guest/Worker/Performer/Volunteer/Speaker for portal comps + createdBy: "Created By", // gate-staff name who issued a comp ticket (portal) // Columns this system manages: code: "Ticket Code", @@ -96,6 +97,7 @@ export interface TicketView { name: string; email: string; ticketType: string; // "" for regular; Guest/Worker/... for special tickets + createdBy: string; // who issued a comp ticket total: number; redeemed: number; remaining: number; @@ -124,6 +126,7 @@ export function toView(rec: NocoRecord): TicketView { name: String(rec[COL.name] ?? ""), email: String(rec[COL.email] ?? ""), ticketType: String(rec[COL.ticketType] ?? ""), + createdBy: String(rec[COL.createdBy] ?? ""), total, redeemed, remaining: Math.max(0, total - redeemed), diff --git a/backend/src/routes/portal.ts b/backend/src/routes/portal.ts index 9a1f077..8c55c0e 100644 --- a/backend/src/routes/portal.ts +++ b/backend/src/routes/portal.ts @@ -22,6 +22,21 @@ export async function portalRoutes(app: FastifyInstance): Promise { reply.type("text/html").send(PAGE); }); + // Password check only (for the in-app portal to gate its form). + app.post( + "/api/portal/verify", + { config: { rateLimit: { max: 20, timeWindow: "1 minute" } } }, + async (req, reply) => { + const cfg = app.ctx.config; + if (!cfg.PORTAL_PASSWORD) return reply.code(404).send({ error: "portal_disabled" }); + const b = (req.body ?? {}) as { password?: string }; + if (!b.password || !safeEqual(b.password, cfg.PORTAL_PASSWORD)) { + return reply.code(401).send({ error: "bad_password" }); + } + return { ok: true, types: TYPES }; + }, + ); + app.post( "/api/portal/create-ticket", { config: { rateLimit: { max: 20, timeWindow: "1 minute" } } }, @@ -29,13 +44,21 @@ export async function portalRoutes(app: FastifyInstance): Promise { const cfg = app.ctx.config; if (!cfg.PORTAL_PASSWORD) return reply.code(404).send({ error: "portal_disabled" }); - const b = (req.body ?? {}) as { password?: string; name?: string; email?: string; type?: string }; + const b = (req.body ?? {}) as { + password?: string; + name?: string; + email?: string; + type?: string; + createdBy?: string; + }; if (!b.password || !safeEqual(b.password, cfg.PORTAL_PASSWORD)) { return reply.code(401).send({ error: "bad_password" }); } const name = String(b.name ?? "").trim(); const email = String(b.email ?? "").trim(); const type = TYPES.includes(String(b.type)) ? String(b.type) : "Guest"; + // Who issued it — from the in-app portal (signed-in gate staff) or header. + const createdBy = String(b.createdBy ?? req.headers["x-operator"] ?? "").slice(0, 80).trim(); if (!name || !email) { return reply.code(400).send({ error: "missing_fields", detail: "name and email are required" }); } @@ -47,6 +70,7 @@ export async function portalRoutes(app: FastifyInstance): Promise { adultNames: [name], email, ticketType: type, + createdBy, counts: { adults: 1, youth: 0, kids12: 0, kids9: 0, kids4: 0 }, submissionKey: `portal:${Date.now()}:${Math.trunc(Math.random() * 1e9)}`, }); diff --git a/backend/src/routes/tickets.ts b/backend/src/routes/tickets.ts index eaa2a67..eb03880 100644 --- a/backend/src/routes/tickets.ts +++ b/backend/src/routes/tickets.ts @@ -2,6 +2,7 @@ import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify"; import { normalizeCode, looksLikeCode } from "../services/code.js"; import { lookupByCode, redeem, search, createTicket } from "../ticketService.js"; import { renderQrPng } from "../services/qrcode.js"; +import { computeStats } from "../services/stats.js"; import { COL } from "../fields.js"; async function requireStaff(req: FastifyRequest, reply: FastifyReply): Promise { @@ -42,6 +43,12 @@ export async function ticketRoutes(app: FastifyInstance): Promise { }, ); + // Aggregate event report (check-in progress, ice, types, extras, operators). + app.get("/api/stats", { preHandler: requireStaff }, async (req) => { + const force = String((req.query as any)?.force ?? "") === "1"; + return computeStats(app.ctx, force); + }); + // Recent check-in audit log (all, or filtered to one code via ?code=). app.get("/api/audit", { preHandler: requireStaff }, async (req) => { const code = (req.query as any)?.code ? normalizeCode(String((req.query as any).code)) : undefined; diff --git a/backend/src/services/audit.ts b/backend/src/services/audit.ts index 05e3b50..2782958 100644 --- a/backend/src/services/audit.ts +++ b/backend/src/services/audit.ts @@ -79,6 +79,43 @@ export class AuditLogger { } } + private mapRow(r: any): AuditRow { + return { + id: r.Id, + code: r[AUDIT_COL.code] ?? "", + people: Number(r[AUDIT_COL.people]) || 0, + name: r[AUDIT_COL.name] ?? "", + operator: r[AUDIT_COL.operator] ?? "", + remainingAfter: Number(r[AUDIT_COL.remainingAfter]) || 0, + at: r[AUDIT_COL.at] ?? r.CreatedAt ?? "", + action: (r[AUDIT_COL.action] ?? "check-in") as AuditEntry["action"], + }; + } + + /** Every audit row, paginated (for reporting/aggregation). */ + async all(): Promise { + if (!this.tableId) return []; + const out: AuditRow[] = []; + const pageSize = 1000; + let offset = 0; + for (;;) { + const url = new URL(this.url); + url.searchParams.set("limit", String(pageSize)); + url.searchParams.set("offset", String(offset)); + const res = await fetch(url.toString(), { + headers: { "xc-token": this.token, "Content-Type": "application/json" }, + }); + if (!res.ok) break; + const body: any = await res.json().catch(() => ({})); + const list = body?.list ?? []; + out.push(...list.map((r: any) => this.mapRow(r))); + if (!list.length || body?.pageInfo?.isLastPage || list.length < pageSize) break; + offset += pageSize; + if (offset > 200000) break; + } + return out; + } + /** Recent entries, newest first, optionally filtered to one code. */ async recent(opts: { code?: string; limit?: number } = {}): Promise { if (!this.tableId) return []; diff --git a/backend/src/services/nocodb.ts b/backend/src/services/nocodb.ts index 707a70a..a9f8587 100644 --- a/backend/src/services/nocodb.ts +++ b/backend/src/services/nocodb.ts @@ -102,6 +102,26 @@ export class NocoDBClient { return (Array.isArray(body) ? body[0] : body) as NocoRecord; } + /** Fetch every record in the table, paginating. */ + async all(): Promise { + const out: NocoRecord[] = []; + const pageSize = 1000; + let offset = 0; + for (;;) { + const url = new URL(this.recordsUrl); + url.searchParams.set("limit", String(pageSize)); + url.searchParams.set("offset", String(offset)); + const body = await this.request(url.toString()); + const list = (body?.list ?? []) as NocoRecord[]; + out.push(...list); + const info = body?.pageInfo; + if (!list.length || info?.isLastPage || list.length < pageSize) break; + offset += pageSize; + if (offset > 200000) break; // safety + } + return out; + } + /** Cheap connectivity probe for healthchecks. */ async ping(): Promise { const url = new URL(this.recordsUrl); diff --git a/backend/src/services/stats.ts b/backend/src/services/stats.ts new file mode 100644 index 0000000..3e9801f --- /dev/null +++ b/backend/src/services/stats.ts @@ -0,0 +1,131 @@ +import type { AppContext } from "../context.js"; +import { COL, toView, toNumber, type NocoRecord } from "../fields.js"; + +export interface Stats { + orders: number; + tickets: { total: number; redeemed: number; remaining: number; pct: number }; + people: { adults: number; youth: number; kids12: number; kids9: number; kids4Free: number }; + ice: { total: number; redeemed: number; remaining: number; pct: number; ticketsSold: number }; + types: { type: string; count: number; total: number; redeemed: number }[]; + donors: { orders: number; members: number; vouchers: number }; + extras: { carParking: number; rvParking: number; utv: number }; + comps: { total: number; byCreator: { name: string; count: number }[] }; + operators: { name: string; checkins: number; ice: number; undos: number }[]; + checkinsByHour: { hour: string; count: number }[]; + generatedAt: string; +} + +let cache: { at: number; data: Stats } | null = null; +const TTL_MS = 20_000; + +export async function computeStats(ctx: AppContext, force = false): Promise { + const now = Date.now(); + if (!force && cache && now - cache.at < TTL_MS) return cache.data; + + const records = await ctx.nocodb.all(); + const bagsPerTicket = ctx.config.ICE_BAGS_PER_TICKET || 3; + + let total = 0, + redeemed = 0, + iceTotal = 0, + iceRedeemed = 0; + let adults = 0, + youth = 0, + kids12 = 0, + kids9 = 0, + kids4 = 0; + let carParking = 0, + rvParking = 0, + utv = 0, + donorOrders = 0, + members = 0, + vouchers = 0; + const typeMap = new Map(); + const compByCreator = new Map(); + let compTotal = 0; + + for (const r of records as NocoRecord[]) { + const v = toView(r); + if (v.ticketType) { + compTotal += 1; + const who = v.createdBy || "(unknown)"; + compByCreator.set(who, (compByCreator.get(who) ?? 0) + 1); + } + total += v.total; + redeemed += v.redeemed; + iceTotal += v.ice.total; + iceRedeemed += v.ice.redeemed; + adults += toNumber(r[COL.adults]); + youth += toNumber(r[COL.youth]); + kids12 += toNumber(r[COL.kids12]); + kids9 += toNumber(r[COL.kids9]); + kids4 += toNumber(r[COL.kids4]); + + const t = v.ticketType || "Regular"; + const e = typeMap.get(t) ?? { count: 0, total: 0, redeemed: 0 }; + e.count += 1; + e.total += v.total; + e.redeemed += v.redeemed; + typeMap.set(t, e); + + if (v.extras.carParking) carParking += 1; + if (v.extras.rvParking) rvParking += 1; + if (v.extras.utv) utv += 1; + if (v.extras.isDonor) donorOrders += 1; + if (v.extras.donorTier === "member") members += 1; + vouchers += v.extras.vouchers; + } + + // Operator activity + check-in timeline from the audit log. + const audit = await ctx.audit.all().catch(() => []); + const opMap = new Map(); + const hourMap = new Map(); + for (const a of audit) { + if (a.operator) { + const o = opMap.get(a.operator) ?? { checkins: 0, ice: 0, undos: 0 }; + if (a.action === "check-in") o.checkins += a.people; + else if (a.action === "undo") o.undos += -a.people; + else if (a.action === "ice") o.ice += a.people; + opMap.set(a.operator, o); + } + if (a.action === "check-in" && a.people > 0 && a.at) { + const hour = String(a.at).slice(0, 13); // YYYY-MM-DDTHH + hourMap.set(hour, (hourMap.get(hour) ?? 0) + a.people); + } + } + + const data: Stats = { + orders: records.length, + tickets: { total, redeemed, remaining: Math.max(0, total - redeemed), pct: total ? Math.round((redeemed / total) * 100) : 0 }, + people: { adults, youth, kids12, kids9, kids4Free: kids4 }, + ice: { + total: iceTotal, + redeemed: iceRedeemed, + remaining: Math.max(0, iceTotal - iceRedeemed), + pct: iceTotal ? Math.round((iceRedeemed / iceTotal) * 100) : 0, + ticketsSold: Math.round(iceTotal / bagsPerTicket), + }, + types: [...typeMap.entries()] + .map(([type, e]) => ({ type, ...e })) + .sort((a, b) => b.total - a.total), + donors: { orders: donorOrders, members, vouchers }, + extras: { carParking, rvParking, utv }, + comps: { + total: compTotal, + byCreator: [...compByCreator.entries()] + .map(([name, count]) => ({ name, count })) + .sort((a, b) => b.count - a.count), + }, + operators: [...opMap.entries()] + .map(([name, o]) => ({ name, ...o })) + .sort((a, b) => b.checkins - a.checkins), + checkinsByHour: [...hourMap.entries()] + .sort((a, b) => (a[0] < b[0] ? -1 : 1)) + .slice(-12) + .map(([hour, count]) => ({ hour, count })), + generatedAt: new Date().toISOString(), + }; + + cache = { at: now, data }; + return data; +} diff --git a/backend/src/ticketService.ts b/backend/src/ticketService.ts index c894f76..040ae07 100644 --- a/backend/src/ticketService.ts +++ b/backend/src/ticketService.ts @@ -131,6 +131,7 @@ export interface WebhookInput { adultNames?: string[]; email: string; ticketType?: string; // Guest/Worker/Performer/Volunteer/Speaker for portal comps + createdBy?: string; // gate-staff name who issued a comp address?: string; isDonor?: boolean; donorTier?: string; @@ -180,6 +181,7 @@ export async function createTicket( }; if (input.adultNames && input.adultNames.length) fields[COL.adultNames] = input.adultNames.join("\n"); if (input.ticketType) fields[COL.ticketType] = input.ticketType; + if (input.createdBy) fields[COL.createdBy] = input.createdBy; if (input.address !== undefined) fields[COL.address] = input.address; if (input.isDonor !== undefined) fields[COL.isDonor] = input.isDonor; if (input.donorTier !== undefined) fields[COL.donorTier] = input.donorTier; From 7296555964f2a43597a51ac9bea48c23299ba500 Mon Sep 17 00:00:00 2001 From: Hank Date: Thu, 16 Jul 2026 05:13:07 +0000 Subject: [PATCH 09/22] Vendor webhooks, free kids through 12, multi-origin lookup CORS Children now free through age 12: - Scannable/paid ticket total = adults + youth 13-16 only; kids 12 & under (0-4, 5-9, 10-12) are stored but not counted (charging starts at 13). computeTotal + freeKidsCount in fields.ts, webhook guard, scan/admin badges, event-report labels, docs, and personas updated. Vendor booth webhooks (vendors.beartariacampgrounds.com): - New /vendor-webhook/food (2 named pass-holders) and /vendor-webhook/non-food (1 pass-holder), reusing WEBHOOK_SECRET. Booth name -> ticket title; each named person = one entry pass; tagged with a "Food Vendor"/"Vendor" Ticket Type (badge on scan + event-report rollup). Idempotent + QR email like the attendee hook. - Extracted shared FluentForms parsing (nameGroup/qty/selected/ addressLine/readDonor) into fluentforms.ts; attendee webhook now imports it. 13 new unit tests. Public lookup CORS is now a comma-separated allowlist; the caller's Origin is echoed only if it matches. tickets + vendors both allowed on donor-eligibility and ticket-vouchers. Co-Authored-By: Claude Opus 4.8 (1M context) --- app/app/admin.tsx | 2 +- app/app/index.tsx | 4 +- app/app/stats.tsx | 8 +- app/lib/api.ts | 2 +- backend/src/config.ts | 12 ++- backend/src/fields.ts | 20 ++-- backend/src/fluentforms.ts | 68 ++++++++++++++ backend/src/routes/publicLookup.ts | 16 ++-- backend/src/routes/test.ts | 8 +- backend/src/routes/vendorWebhook.ts | 133 +++++++++++++++++++++++++++ backend/src/routes/webhook.ts | 65 ++----------- backend/src/routes/webhookDoc.ts | 25 ++++- backend/src/server.ts | 2 + backend/src/test/fields.test.ts | 10 +- backend/src/test/fluentforms.test.ts | 84 +++++++++++++++++ 15 files changed, 368 insertions(+), 91 deletions(-) create mode 100644 backend/src/fluentforms.ts create mode 100644 backend/src/routes/vendorWebhook.ts create mode 100644 backend/src/test/fluentforms.test.ts diff --git a/app/app/admin.tsx b/app/app/admin.tsx index 92b4052..4d1a277 100644 --- a/app/app/admin.tsx +++ b/app/app/admin.tsx @@ -209,7 +209,7 @@ function TicketCard({ ticket, onAdjust }: { ticket: TicketView; onAdjust: (t: Ti if (e.rvParking) tags.push("🚐 RV"); if (e.utv) tags.push("🏍️ UTV"); if (e.iceAccess || ticket.ice.total > 0) tags.push(`🧊 ${ticket.ice.remaining}/${ticket.ice.total}`); - if (e.freeUnder5 > 0) tags.push(`👶 ${e.freeUnder5} free`); + if (e.freeKids > 0) tags.push(`👶 ${e.freeKids} free kids`); return ( diff --git a/app/app/index.tsx b/app/app/index.tsx index c3bcdbc..d3211da 100644 --- a/app/app/index.tsx +++ b/app/app/index.tsx @@ -346,7 +346,7 @@ function ExtrasRow({ ticket }: { ticket: TicketView }) { if (e.rvParking) tags.push("🚐 RV parking"); if (e.utv) tags.push("🏍️ UTV/ATV"); if (e.iceAccess || ticket.ice.total > 0) tags.push(`🧊 ${ticket.ice.remaining}/${ticket.ice.total} ice`); - if (e.freeUnder5 > 0) tags.push(`👶 ${e.freeUnder5} under 5 (free)`); + if (e.freeKids > 0) tags.push(`👶 ${e.freeKids} ${e.freeKids === 1 ? "kid" : "kids"} 12 & under (free)`); if (!tags.length) return null; return ( @@ -365,6 +365,8 @@ const TYPE_ICON: Record = { Performer: "🎭", Volunteer: "🙌", Speaker: "🎤", + "Food Vendor": "🍔", + Vendor: "🛒", }; function TypeBadge({ type }: { type: string }) { diff --git a/app/app/stats.tsx b/app/app/stats.tsx index 9c9428a..acd8c84 100644 --- a/app/app/stats.tsx +++ b/app/app/stats.tsx @@ -13,6 +13,8 @@ const TYPE_ICON: Record = { Performer: "🎭", Volunteer: "🙌", Speaker: "🎤", + "Food Vendor": "🍔", + Vendor: "🛒", }; const MEDAL = ["🥇", "🥈", "🥉"]; @@ -138,9 +140,9 @@ export default function StatsScreen() { Who's coming - - - + + + diff --git a/app/lib/api.ts b/app/lib/api.ts index ccc02e8..9f9d4f1 100644 --- a/app/lib/api.ts +++ b/app/lib/api.ts @@ -36,7 +36,7 @@ export interface TicketView { isDonor: boolean; donorTier: string; vouchers: number; - freeUnder5: number; + freeKids: number; }; ages: { bracket: string; count: number; free: boolean }[]; } diff --git a/backend/src/config.ts b/backend/src/config.ts index ef9f7f5..88954cf 100644 --- a/backend/src/config.ts +++ b/backend/src/config.ts @@ -27,7 +27,17 @@ const schema = z.object({ // Disabled unless a secret is set. Returns only eligibility + tier, never // names or dollar amounts. Rate-limited + CORS-restricted. PUBLIC_LOOKUP_SECRET: z.string().optional(), - PUBLIC_LOOKUP_ORIGIN: z.string().default("https://tickets.beartariacampgrounds.com"), + // Comma-separated allowlist of browser origins permitted to call the public + // lookups (the request's Origin is echoed back only if it matches one). + PUBLIC_LOOKUP_ORIGIN: z + .string() + .default("https://tickets.beartariacampgrounds.com,https://vendors.beartariacampgrounds.com") + .transform((s) => + s + .split(",") + .map((o) => o.trim().replace(/\/+$/, "")) + .filter(Boolean), + ), // Ticket-voucher entitlement: donations on/after VOUCHER_SINCE totalling // >= TIER1 earn 1 voucher, >= TIER2 earn 2. Bump the date each year. diff --git a/backend/src/fields.ts b/backend/src/fields.ts index 50c569d..ae4dbf9 100644 --- a/backend/src/fields.ts +++ b/backend/src/fields.ts @@ -51,11 +51,17 @@ function bool(v: unknown): boolean { } /** - * Total scannable tickets = everyone except kids 0-4 (who are free): - * adults + youth (13-16) + kids 10-12 + kids 5-9. + * Total scannable (paid) tickets = adults + youth 13-16. Children 12 and under + * (kids 10-12 / 5-9 / 0-4) are admitted free and not counted; charging starts + * at age 13. */ export function computeTotal(rec: NocoRecord): number { - return num(rec[COL.adults]) + num(rec[COL.youth]) + num(rec[COL.kids12]) + num(rec[COL.kids9]); + return num(rec[COL.adults]) + num(rec[COL.youth]); +} + +/** Free children (age 12 and under). */ +export function freeKidsCount(rec: NocoRecord): number { + return num(rec[COL.kids12]) + num(rec[COL.kids9]) + num(rec[COL.kids4]); } export function computeIceTotal(rec: NocoRecord): number { @@ -67,8 +73,8 @@ export function ageBreakdown(rec: NocoRecord): { bracket: string; count: number; return [ { bracket: "Adults", count: num(rec[COL.adults]), free: false }, { bracket: "Youth 13-16", count: num(rec[COL.youth]), free: false }, - { bracket: "Kids 10-12", count: num(rec[COL.kids12]), free: false }, - { bracket: "Kids 5-9", count: num(rec[COL.kids9]), free: false }, + { bracket: "Kids 10-12", count: num(rec[COL.kids12]), free: true }, + { bracket: "Kids 5-9", count: num(rec[COL.kids9]), free: true }, { bracket: "Kids 0-4", count: num(rec[COL.kids4]), free: true }, ].filter((b) => b.count > 0); } @@ -111,7 +117,7 @@ export interface TicketView { isDonor: boolean; donorTier: string; vouchers: number; - freeUnder5: number; + freeKids: number; // children 12 & under (free admission) }; ages: { bracket: string; count: number; free: boolean }[]; } @@ -144,7 +150,7 @@ export function toView(rec: NocoRecord): TicketView { isDonor: bool(rec[COL.isDonor]), donorTier: String(rec[COL.donorTier] ?? ""), vouchers: num(rec[COL.vouchers]), - freeUnder5: num(rec[COL.kids4]), + freeKids: freeKidsCount(rec), }, ages: ageBreakdown(rec), }; diff --git a/backend/src/fluentforms.ts b/backend/src/fluentforms.ts new file mode 100644 index 0000000..de628a7 --- /dev/null +++ b/backend/src/fluentforms.ts @@ -0,0 +1,68 @@ +import { timingSafeEqual } from "node:crypto"; +import { toBool, toNumber } from "./fields.js"; + +/** Constant-time string compare for shared webhook secrets. */ +export function safeEqual(a: string, b: string): boolean { + const ba = Buffer.from(a || ""); + const bb = Buffer.from(b || ""); + if (ba.length !== bb.length) return false; + return timingSafeEqual(ba, bb); +} + +/** Read a FluentForms compound name field, given as a nested object + * (`names: {first_name,...}`) or flattened bracket keys (`names[first_name]`). */ +export function nameGroup(body: Record, base: string): string { + const obj = body[base]; + let first: any, middle: any, last: any; + if (obj && typeof obj === "object") { + ({ first_name: first, middle_name: middle, last_name: last } = obj); + } else { + first = body[`${base}[first_name]`]; + middle = body[`${base}[middle_name]`]; + last = body[`${base}[last_name]`]; + } + return [first, middle, last] + .map((x) => (x == null ? "" : String(x).trim())) + .filter(Boolean) + .join(" "); +} + +/** Read an item_quantity / payment field's numeric value (handles nested + * objects like {quantity} / {value} and money strings like "$40.00"). */ +export function qty(v: any): number { + if (v == null || v === "") return 0; + if (typeof v === "object") return toNumber(v.quantity ?? v.value ?? v.item_quantity ?? v.amount ?? 0); + if (typeof v === "string") return toNumber(v.replace(/[^0-9.\-]/g, "")); + return toNumber(v); +} + +/** A payment/extra field counts as "selected" if it has a meaningful value. + * Donor (free) items can be $0, so a non-empty, non-"no"/"0" value also counts. */ +export function selected(v: any): boolean { + if (v == null || v === "") return false; + if (typeof v === "object") { + if ("selected" in v) return toBool((v as any).selected); + return qty(v) > 0 || Object.keys(v).length > 0; + } + const s = String(v).trim().toLowerCase(); + if (!s || s === "no" || s === "0" || s === "$0" || s === "$0.00" || s === "false" || s === "none") return false; + return true; +} + +/** Flatten a FluentForms compound address (`address_1`) to a single line. */ +export function addressLine(v: any): string | undefined { + if (v && typeof v === "object") return Object.values(v).filter(Boolean).join(", "); + if (v !== undefined) return String(v); + return undefined; +} + +/** Donor status from the hidden lookup fields + the "are you a donor?" radio. */ +export function readDonor(body: Record): { isDonor: boolean; donorTier: string } { + const donorTier = String(body.donor_tier ?? "").trim(); + const isDonor = + donorTier === "member" || + donorTier === "donor" || + toBool(body.donor_eligible) || + selected(body.input_radio); // "Are you a campground donor?" + return { isDonor, donorTier }; +} diff --git a/backend/src/routes/publicLookup.ts b/backend/src/routes/publicLookup.ts index c804b30..d1437f9 100644 --- a/backend/src/routes/publicLookup.ts +++ b/backend/src/routes/publicLookup.ts @@ -17,17 +17,21 @@ function safeEqual(a: string, b: string): boolean { */ export async function publicLookupRoutes(app: FastifyInstance): Promise { const cfg = app.ctx.config; - const origin = cfg.PUBLIC_LOOKUP_ORIGIN; + const allowed = cfg.PUBLIC_LOOKUP_ORIGIN; // string[] allowlist - const cors = (reply: any) => { + const cors = (req: any, reply: any) => { + const reqOrigin = String(req.headers?.origin ?? "").replace(/\/+$/, ""); + // Echo the caller's origin only if it's on the allowlist; otherwise fall + // back to the first configured origin (keeps non-browser callers working). + const origin = allowed.includes(reqOrigin) ? reqOrigin : allowed[0]; reply.header("Access-Control-Allow-Origin", origin); reply.header("Vary", "Origin"); reply.header("Access-Control-Allow-Methods", "GET, OPTIONS"); }; // Preflight (in case the form sends one). - const preflight = async (_req: any, reply: any) => { - cors(reply); + const preflight = async (req: any, reply: any) => { + cors(req, reply); return reply.code(204).send(); }; app.options("/api/public/donor-eligibility", preflight); @@ -42,7 +46,7 @@ export async function publicLookupRoutes(app: FastifyInstance): Promise { "/api/public/donor-eligibility", { config: { rateLimit: { max: 30, timeWindow: "1 minute" } } }, async (req, reply) => { - cors(reply); + cors(req, reply); // Disabled unless configured. if (!cfg.PUBLIC_LOOKUP_SECRET || !app.ctx.donors.enabled) { return reply.code(404).send({ error: "not_available" }); @@ -72,7 +76,7 @@ export async function publicLookupRoutes(app: FastifyInstance): Promise { "/api/public/ticket-vouchers", { config: { rateLimit: { max: 30, timeWindow: "1 minute" } } }, async (req, reply) => { - cors(reply); + cors(req, reply); if (!cfg.PUBLIC_LOOKUP_SECRET || !app.ctx.donors.enabled) { return reply.code(404).send({ error: "not_available" }); } diff --git a/backend/src/routes/test.ts b/backend/src/routes/test.ts index 1096416..a82c0f3 100644 --- a/backend/src/routes/test.ts +++ b/backend/src/routes/test.ts @@ -37,11 +37,11 @@ const PERSONAS: Persona[] = [ name: "Family Fay", email: "family@test.beartaria", adultNames: ["Family Fay", "Frank Fay"], - counts: C(2, 0, 0, 3, 2), // 2 adults + 3 kids(5-9) = 5 scannable; 2 kids 0-4 free + counts: C(2, 1, 1, 2, 2), // 2 adults + 1 youth = 3 paid; 5 kids 12 & under free iceBags: 3, carParking: true, blurb: - "5 tickets (2 adults + 3 kids 5-9; two 0-4 free), car parking, 3 ice bags. Check-in a few at a time to test QR reuse + see adult names; then Ice mode.", + "3 paid tickets (2 adults + 1 youth 13-16); 5 kids 12 & under free; car parking, 3 ice bags. Check-in a few at a time to test QR reuse + see adult names; then Ice mode.", }, { key: "donor2", @@ -119,8 +119,8 @@ export async function testRoutes(app: FastifyInstance): Promise { // Keep the "exhausted" persona fully redeemed on every load so its state // is deterministic (total = scannable count from the persona's counts). if (p.exhaust) { - const { adults, youth, kids12, kids9 } = p.counts; - await app.ctx.nocodb.update(result.record.Id, { [COL.redeemed]: adults + youth + kids12 + kids9 }); + const { adults, youth } = p.counts; + await app.ctx.nocodb.update(result.record.Id, { [COL.redeemed]: adults + youth }); } cards.push({ code: result.code, diff --git a/backend/src/routes/vendorWebhook.ts b/backend/src/routes/vendorWebhook.ts new file mode 100644 index 0000000..95eb076 --- /dev/null +++ b/backend/src/routes/vendorWebhook.ts @@ -0,0 +1,133 @@ +import { createHash } from "node:crypto"; +import type { FastifyInstance } from "fastify"; +import { createTicket } from "../ticketService.js"; +import { renderQrPng } from "../services/qrcode.js"; +import { safeEqual, nameGroup, addressLine, readDonor } from "../fluentforms.js"; + +/** + * Vendor booth webhooks (Vendor Fee Food / Non-Food 2026, on + * vendors.beartariacampgrounds.com). Structurally these are the same form; the + * only difference is how many entry passes a booth includes: + * + * - Food: two named pass-holders (`names` = "Name Ticket 1", + * `names_1` = "Name Ticket #2") → up to 2 passes. + * - Non-Food: one named pass-holder (`names`) → 1 pass. + * + * Each named person gets one gate ticket. The booth name becomes the ticket + * title (so gate staff see the booth) and the pass-holders are stored as the + * attendee names. The ticket is tagged with a vendor `Ticket Type` so it shows + * a badge on scan and rolls up in the event report. Booth size / additional + * space are logistics, not admissions, so they don't affect the pass count. + * + * Shares WEBHOOK_SECRET with the attendee webhook (same X-Webhook-Secret header). + */ +interface VendorKind { + ticketType: string; // badge label shown on scan + nameSlots: string[]; // pass-holder name field bases, in order +} + +const KINDS: Record<"food" | "nonfood", VendorKind> = { + food: { ticketType: "Food Vendor", nameSlots: ["names", "names_1"] }, + nonfood: { ticketType: "Vendor", nameSlots: ["names"] }, +}; + +function makeHandler(app: FastifyInstance, kind: VendorKind) { + return async (req: any, reply: any) => { + const secret = req.headers["x-webhook-secret"]; + if (typeof secret !== "string" || !safeEqual(secret, app.ctx.config.WEBHOOK_SECRET)) { + return reply.code(401).send({ error: "unauthorized" }); + } + + const body = (req.body ?? {}) as Record; + + const boothName = String(body.input_text ?? "").trim(); + // Pass-holder names (non-empty slots, in order). + const passHolders = kind.nameSlots.map((b) => nameGroup(body, b)).filter(Boolean); + const primary = passHolders[0] ?? ""; + // Ticket title = booth name (most useful at the gate), else the first person. + const title = boothName || primary; + if (!title) { + return reply.code(400).send({ error: "missing_fields", detail: "booth name or vendor name is required" }); + } + + const email = String(body.email ?? "").trim(); + // One entry pass per named person; a booth with no names still gets 1. + const passes = Math.max(1, passHolders.length); + + const { isDonor, donorTier } = readDonor(body); + const address = addressLine(body.address_1); + + // Idempotency: prefer a stable submission id, else hash the content. + const submissionId = body.submission_id ?? body.submissionId ?? body.entry_id ?? body.id; + const submissionKey = submissionId + ? `sub:${String(submissionId)}` + : "hash:" + + createHash("sha256") + .update(`vendor|${kind.ticketType}|${email}|${title}|${passes}`) + .digest("hex") + .slice(0, 32); + + // Vendor passes are adult admissions; no youth/kids/ice/parking. + const counts = { adults: passes, youth: 0, kids12: 0, kids9: 0, kids4: 0 }; + + let result: Awaited>; + try { + result = await createTicket(app.ctx, { + name: title, + adultNames: passHolders, + email, + address, + isDonor, + donorTier, + ticketType: kind.ticketType, + counts, + paymentMethod: body.payment_method !== undefined ? String(body.payment_method) : undefined, + submissionKey, + }); + } catch (e: any) { + req.log.error({ err: e }, "vendor webhook: failed to create ticket"); + return reply.code(502).send({ error: "db_error", detail: e?.message }); + } + + if (result.status === "duplicate") { + return { status: "duplicate", code: result.code }; + } + + // Email the ticket QR (FluentForms sends the receipt separately). + if (!email) { + req.log.warn({ code: result.code }, "vendor webhook: ticket created but no email"); + return { status: "created", code: result.code, passes, emailSent: false, emailSkipped: "no_email" }; + } + if (app.ctx.mailer.isBlockedRecipient(email)) { + req.log.warn({ email }, "vendor webhook: recipient blocked by MAIL_TEST_RECIPIENTS; skipping send"); + return { status: "created", code: result.code, passes, emailSent: false, emailSkipped: "trial_restriction" }; + } + + try { + const qr = await renderQrPng(result.code); + await app.ctx.mailer.sendTicket({ + toEmail: email, + toName: primary || title, + code: result.code, + quantity: passes, + qrPng: qr, + }); + } catch (e: any) { + req.log.error({ err: e, code: result.code }, "vendor webhook: created but email failed"); + return reply.code(502).send({ status: "created", code: result.code, passes, emailSent: false, error: e?.message }); + } + + return { status: "created", code: result.code, passes, emailSent: true }; + }; +} + +export async function vendorWebhookRoutes(app: FastifyInstance): Promise { + // Configure these URLs in the two FluentForms vendor forms: + // Food: https://scan.beartariacampgrounds.com/vendor-webhook/food + // Non-Food: https://scan.beartariacampgrounds.com/vendor-webhook/non-food + app.post("/vendor-webhook/food", makeHandler(app, KINDS.food)); + app.post("/vendor-webhook/non-food", makeHandler(app, KINDS.nonfood)); + // Explicit API aliases. + app.post("/api/webhook/vendor-food", makeHandler(app, KINDS.food)); + app.post("/api/webhook/vendor-non-food", makeHandler(app, KINDS.nonfood)); +} diff --git a/backend/src/routes/webhook.ts b/backend/src/routes/webhook.ts index 9d96961..77d7522 100644 --- a/backend/src/routes/webhook.ts +++ b/backend/src/routes/webhook.ts @@ -1,55 +1,9 @@ -import { createHash, timingSafeEqual } from "node:crypto"; +import { createHash } from "node:crypto"; import type { FastifyInstance } from "fastify"; -import { toBool, toNumber } from "../fields.js"; +import { toBool } from "../fields.js"; import { createTicket } from "../ticketService.js"; import { renderQrPng } from "../services/qrcode.js"; - -function safeEqual(a: string, b: string): boolean { - const ba = Buffer.from(a || ""); - const bb = Buffer.from(b || ""); - if (ba.length !== bb.length) return false; - return timingSafeEqual(ba, bb); -} - -/** Read a FluentForms compound name field, given as a nested object - * (`names: {first_name,...}`) or flattened bracket keys (`names[first_name]`). */ -function nameGroup(body: Record, base: string): string { - const obj = body[base]; - let first: any, middle: any, last: any; - if (obj && typeof obj === "object") { - ({ first_name: first, middle_name: middle, last_name: last } = obj); - } else { - first = body[`${base}[first_name]`]; - middle = body[`${base}[middle_name]`]; - last = body[`${base}[last_name]`]; - } - return [first, middle, last] - .map((x) => (x == null ? "" : String(x).trim())) - .filter(Boolean) - .join(" "); -} - -/** Read an item_quantity / payment field's numeric value (handles nested - * objects like {quantity} / {value} and money strings like "$40.00"). */ -function qty(v: any): number { - if (v == null || v === "") return 0; - if (typeof v === "object") return toNumber(v.quantity ?? v.value ?? v.item_quantity ?? v.amount ?? 0); - if (typeof v === "string") return toNumber(v.replace(/[^0-9.\-]/g, "")); - return toNumber(v); -} - -/** A payment/extra field counts as "selected" if it has a meaningful value. - * Donor (free) items can be $0, so a non-empty, non-"no"/"0" value also counts. */ -function selected(v: any): boolean { - if (v == null || v === "") return false; - if (typeof v === "object") { - if ("selected" in v) return toBool((v as any).selected); - return qty(v) > 0 || Object.keys(v).length > 0; - } - const s = String(v).trim().toLowerCase(); - if (!s || s === "no" || s === "0" || s === "$0" || s === "$0.00" || s === "false" || s === "none") return false; - return true; -} +import { safeEqual, nameGroup, qty, selected, addressLine } from "../fluentforms.js"; // Adult name field bases, in order (purchaser first). const ADULT_NAME_BASES = ["names", "names_1", "names_2", "names_3", "names_4", "names_5", "names_6", "names_7", "names_8", "names_9"]; @@ -81,11 +35,13 @@ export async function webhookRoutes(app: FastifyInstance): Promise { kids9: qty(body.item_quantity_kids_9), kids4: qty(body.item_quantity_kids_4), }; - const scannable = counts.adults + counts.youth + counts.kids12 + counts.kids9; + // Paid/scannable admissions = adults + youth 13-16. Children 12 & under are + // free (charging starts at 13) and are stored but not counted at the gate. + const scannable = counts.adults + counts.youth; if (scannable <= 0) { // Nothing to check in at the gate. Log the payload so we can calibrate. req.log.warn({ body }, "webhook: no scannable tickets in submission"); - return reply.code(400).send({ error: "no_tickets", detail: "no scannable tickets (adults/youth/kids 5+)" }); + return reply.code(400).send({ error: "no_tickets", detail: "no paid tickets (adults / youth 13-16)" }); } // Donor info (hidden fields from the eligibility/voucher lookups) + radio. @@ -108,12 +64,7 @@ export async function webhookRoutes(app: FastifyInstance): Promise { const iceBags = Math.max(0, iceTickets) * app.ctx.config.ICE_BAGS_PER_TICKET; const iceAccess = iceBags > 0 || selected(body.input_radio_7); - const address = - body.address_1 && typeof body.address_1 === "object" - ? Object.values(body.address_1).filter(Boolean).join(", ") - : body.address_1 !== undefined - ? String(body.address_1) - : undefined; + const address = addressLine(body.address_1); // Idempotency: prefer a stable submission id, else hash the content. const submissionId = body.submission_id ?? body.submissionId ?? body.entry_id ?? body.id; diff --git a/backend/src/routes/webhookDoc.ts b/backend/src/routes/webhookDoc.ts index 8f7bd8a..276062b 100644 --- a/backend/src/routes/webhookDoc.ts +++ b/backend/src/routes/webhookDoc.ts @@ -18,9 +18,9 @@ const FIELDS: Field[] = [ { key: "item_quantity_adult_ticket_reg", req: "required", type: "quantity", desc: "Adult tickets (regular)." }, { key: "item_quantity_adult_ticket_donor", req: "required", type: "quantity", desc: "Adult tickets (donor). Added to the regular adults." }, { key: "item_quantity_youth_ticket_reg / _donor", req: "optional", type: "quantity", desc: "Youth 13-16 tickets (regular + donor)." }, - { key: "item_quantity_kids_12", req: "optional", type: "quantity", desc: "Kids 10-12. Counts toward the scannable total." }, - { key: "item_quantity_kids_9", req: "optional", type: "quantity", desc: "Kids 5-9. Counts toward the scannable total." }, - { key: "item_quantity_kids_4", req: "optional", type: "quantity", desc: "Kids 0-4. FREE — NOT counted toward the scannable ticket total." }, + { key: "item_quantity_kids_12", req: "optional", type: "quantity", desc: "Kids 10-12. FREE — stored but NOT counted toward the scannable ticket total." }, + { key: "item_quantity_kids_9", req: "optional", type: "quantity", desc: "Kids 5-9. FREE — stored but NOT counted toward the scannable ticket total." }, + { key: "item_quantity_kids_4", req: "optional", type: "quantity", desc: "Kids 0-4. FREE — stored but NOT counted toward the scannable ticket total." }, { key: "donor_tier", req: "optional", type: "hidden", desc: "member / donor / empty (from the donor-eligibility lookup)." }, { key: "donor_eligible", req: "optional", type: "hidden", desc: "true / false (from the donor-eligibility lookup)." }, { key: "vouchers", req: "optional", type: "hidden", desc: "Integer voucher count (from the ticket-voucher lookup)." }, @@ -118,7 +118,7 @@ const PAGE = `

What it does

On a valid request the backend generates a unique ticket code, creates a NocoDB row, and emails the QR code to the purchaser (subject "2026 Beartaria Campgrounds Tickets"). FluentForms sends the payment receipt separately.

-

Scannable ticket total = adults + youth (13-16) + kids 10-12 + kids 5-9. Kids 0-4 are free and not counted. Each adult name provided is stored and shown to gate staff on a successful scan.

+

Scannable ticket total = adults + youth (13-16). Children 12 & under are free (charging starts at 13) — their counts are stored and shown to gate staff, but not counted toward the ticket total. Each adult name provided is stored and shown on a successful scan.

Fields

@@ -132,7 +132,7 @@ const PAGE = `

Example payload

${exampleJson}
-

This issues 5 scannable tickets (2 adults + 1 youth + 2 kids 5-9; the two kids 0-4 are free), member donor with 2 vouchers, car parking, and 6 bags of ice (2 ice tickets).

+

This issues 3 scannable tickets (2 adults + 1 youth 13-16; all four kids 12 & under are free), member donor with 2 vouchers, car parking, and 6 bags of ice (2 ice tickets).

Test with curl

${exampleCurl}
@@ -158,6 +158,21 @@ const PAGE = `
  • Save, submit a test purchase, and confirm the QR email arrives.
  • +

    Vendor booth webhooks

    +

    The two vendor forms on vendors.beartariacampgrounds.com post to their own endpoints (same X-Webhook-Secret). Each named booth person gets one entry pass; the booth name (input_text) becomes the ticket title, and the ticket is tagged with a vendor Ticket Type that shows a badge on scan and rolls up in the event report. Booth size / additional space are logistics and don't affect passes.

    +
    + + + + + +
    FormEndpointPassesTicket Type
    Vendor Fee Food 2026POST /vendor-webhook/foodup to 2 (names + names_1)🍔 Food Vendor
    Vendor Fee Non-Food 2026POST /vendor-webhook/non-food1 (names)🛒 Vendor
    +

    Relevant keys: input_text (Booth Name), names / names_1 (pass-holders), email, address_1, donor_tier / donor_eligible / input_radio (donor), payment_method. Same idempotency (id/submission_id) and response shapes as above, plus a passes count.

    +
    curl -X POST https://scan.beartariacampgrounds.com/vendor-webhook/food \\
    +  -H "Content-Type: application/json" \\
    +  -H "X-Webhook-Secret: <your WEBHOOK_SECRET>" \\
    +  -d '{"id":"v-101","input_text":"Joe'\\''s Tacos","names":{"first_name":"Joe","last_name":"Taco"},"names_1":{"first_name":"Jane","last_name":"Taco"},"email":"joe@example.com","donor_tier":"member","payment_method":"stripe"}'
    +
    Beartaria Campgrounds · scan.beartariacampgrounds.com
    diff --git a/backend/src/server.ts b/backend/src/server.ts index b10433e..7895fe1 100644 --- a/backend/src/server.ts +++ b/backend/src/server.ts @@ -9,6 +9,7 @@ import { loadConfig } from "./config.js"; import { buildContext } from "./context.js"; import { authRoutes } from "./routes/auth.js"; import { webhookRoutes } from "./routes/webhook.js"; +import { vendorWebhookRoutes } from "./routes/vendorWebhook.js"; import { ticketRoutes } from "./routes/tickets.js"; import { testRoutes } from "./routes/test.js"; import { installRoutes } from "./routes/install.js"; @@ -32,6 +33,7 @@ export async function build() { await app.register(authRoutes); await app.register(webhookRoutes); + await app.register(vendorWebhookRoutes); await app.register(ticketRoutes); await app.register(testRoutes); await app.register(installRoutes); diff --git a/backend/src/test/fields.test.ts b/backend/src/test/fields.test.ts index 834de59..be0a4f1 100644 --- a/backend/src/test/fields.test.ts +++ b/backend/src/test/fields.test.ts @@ -2,16 +2,16 @@ import { describe, it, expect } from "vitest"; import { computeTotal, toView, COL } from "../fields.js"; describe("computeTotal", () => { - it("sums adults + youth + kids 10-12 + kids 5-9, excluding kids 0-4 (free)", () => { + it("sums adults + youth 13-16 only; all kids 12 & under are free", () => { const rec = { Id: 1, [COL.adults]: 2, [COL.youth]: 1, - [COL.kids12]: 1, - [COL.kids9]: 1, + [COL.kids12]: 1, // free, not counted + [COL.kids9]: 1, // free, not counted [COL.kids4]: 3, // free, not counted }; - expect(computeTotal(rec)).toBe(5); + expect(computeTotal(rec)).toBe(3); }); it("coerces string counts and treats blanks as 0", () => { @@ -47,7 +47,7 @@ describe("toView", () => { expect(v.extras.rvParking).toBe(false); expect(v.extras.donorTier).toBe("member"); expect(v.extras.vouchers).toBe(2); - expect(v.extras.freeUnder5).toBe(1); + expect(v.extras.freeKids).toBe(1); expect(v.ages.find((a) => a.bracket === "Kids 0-4")?.free).toBe(true); }); }); diff --git a/backend/src/test/fluentforms.test.ts b/backend/src/test/fluentforms.test.ts new file mode 100644 index 0000000..4f21e4b --- /dev/null +++ b/backend/src/test/fluentforms.test.ts @@ -0,0 +1,84 @@ +import { describe, it, expect } from "vitest"; +import { nameGroup, qty, selected, addressLine, readDonor } from "../fluentforms.js"; + +// Pass-holder name slots per the two vendor forms. +const FOOD_SLOTS = ["names", "names_1"]; +const NONFOOD_SLOTS = ["names"]; + +/** Mirror the vendor handler's pass count: one per named person, min 1. */ +function passCount(body: Record, slots: string[]): number { + const holders = slots.map((b) => nameGroup(body, b)).filter(Boolean); + return Math.max(1, holders.length); +} + +describe("nameGroup", () => { + it("reads flattened bracket keys", () => { + const body = { "names[first_name]": "Joe", "names[last_name]": "Taco" }; + expect(nameGroup(body, "names")).toBe("Joe Taco"); + }); + it("reads a nested object and includes the middle name", () => { + const body = { names: { first_name: "Ann", middle_name: "B", last_name: "Cole" } }; + expect(nameGroup(body, "names")).toBe("Ann B Cole"); + }); + it("returns empty string when the group is blank", () => { + expect(nameGroup({}, "names_1")).toBe(""); + }); +}); + +describe("vendor pass counting", () => { + it("food booth with two named holders gets 2 passes", () => { + const body = { + input_text: "Joe's Tacos", + "names[first_name]": "Joe", + "names[last_name]": "Taco", + "names_1[first_name]": "Jane", + "names_1[last_name]": "Taco", + }; + expect(passCount(body, FOOD_SLOTS)).toBe(2); + }); + it("food booth with only the first name gets 1 pass", () => { + const body = { input_text: "Solo BBQ", "names[first_name]": "Sam", "names[last_name]": "Que" }; + expect(passCount(body, FOOD_SLOTS)).toBe(1); + }); + it("non-food booth gets 1 pass (only one name slot)", () => { + const body = { + input_text: "Craft Corner", + "names[first_name]": "Pat", + "names[last_name]": "Maker", + // a stray names_1 must NOT count for non-food + "names_1[first_name]": "Ignore", + }; + expect(passCount(body, NONFOOD_SLOTS)).toBe(1); + }); + it("booth with no names still gets 1 pass", () => { + expect(passCount({ input_text: "Nameless Booth" }, FOOD_SLOTS)).toBe(1); + }); +}); + +describe("readDonor", () => { + it("treats donor_tier=member as a donor", () => { + expect(readDonor({ donor_tier: "member" })).toEqual({ isDonor: true, donorTier: "member" }); + }); + it("honors the donor_eligible hidden flag", () => { + expect(readDonor({ donor_eligible: "true" }).isDonor).toBe(true); + }); + it("is not a donor when nothing indicates it", () => { + expect(readDonor({ input_radio: "No" })).toEqual({ isDonor: false, donorTier: "" }); + }); +}); + +describe("qty / selected / addressLine", () => { + it("parses money strings and nested quantities", () => { + expect(qty("$40.00")).toBe(40); + expect(qty({ quantity: 2 })).toBe(2); + expect(qty("")).toBe(0); + }); + it("selected() treats $0.00 / no / blank as unselected", () => { + expect(selected("$0.00")).toBe(false); + expect(selected("No")).toBe(false); + expect(selected("Yes")).toBe(true); + }); + it("flattens a compound address", () => { + expect(addressLine({ address_line_1: "1 Main", city: "Boise", state: "ID" })).toBe("1 Main, Boise, ID"); + }); +}); From 267957d333446638badb3d0a0cf221d919318518 Mon Sep 17 00:00:00 2001 From: Hank Date: Thu, 16 Jul 2026 21:57:22 +0000 Subject: [PATCH 10/22] Non-food vendors get no entry ticket MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only food vendors receive gate passes. The /vendor-webhook/non-food endpoint now acknowledges the submission ({"status":"ignored"}) and issues nothing, instead of creating a 1-pass ticket — kept as a safe no-op so an accidentally-wired FluentForms feed doesn't 404. Food webhook unchanged. Doc + tests updated. Co-Authored-By: Claude Opus 4.8 (1M context) --- backend/src/routes/vendorWebhook.ts | 72 +++++++++++++++------------- backend/src/routes/webhookDoc.ts | 10 ++-- backend/src/test/fluentforms.test.ts | 17 ++----- 3 files changed, 48 insertions(+), 51 deletions(-) diff --git a/backend/src/routes/vendorWebhook.ts b/backend/src/routes/vendorWebhook.ts index 95eb076..86722c2 100644 --- a/backend/src/routes/vendorWebhook.ts +++ b/backend/src/routes/vendorWebhook.ts @@ -6,35 +6,31 @@ import { safeEqual, nameGroup, addressLine, readDonor } from "../fluentforms.js" /** * Vendor booth webhooks (Vendor Fee Food / Non-Food 2026, on - * vendors.beartariacampgrounds.com). Structurally these are the same form; the - * only difference is how many entry passes a booth includes: + * vendors.beartariacampgrounds.com). Only FOOD vendors receive entry tickets: * * - Food: two named pass-holders (`names` = "Name Ticket 1", - * `names_1` = "Name Ticket #2") → up to 2 passes. - * - Non-Food: one named pass-holder (`names`) → 1 pass. + * `names_1` = "Name Ticket #2") → up to 2 gate passes. + * - Non-Food: NO entry ticket. The endpoint acknowledges the submission + * (so a wired FluentForms feed doesn't error) but issues nothing. * - * Each named person gets one gate ticket. The booth name becomes the ticket - * title (so gate staff see the booth) and the pass-holders are stored as the - * attendee names. The ticket is tagged with a vendor `Ticket Type` so it shows - * a badge on scan and rolls up in the event report. Booth size / additional - * space are logistics, not admissions, so they don't affect the pass count. + * For food, each named person gets one gate ticket. The booth name becomes the + * ticket title (so gate staff see the booth) and the pass-holders are stored as + * the attendee names. The ticket is tagged with a "Food Vendor" `Ticket Type` + * so it shows a badge on scan and rolls up in the event report. Booth size / + * additional space are logistics, not admissions, so they don't affect passes. * * Shares WEBHOOK_SECRET with the attendee webhook (same X-Webhook-Secret header). */ -interface VendorKind { - ticketType: string; // badge label shown on scan - nameSlots: string[]; // pass-holder name field bases, in order +const FOOD_NAME_SLOTS = ["names", "names_1"]; // pass-holder name field bases + +function checkSecret(app: FastifyInstance, req: any): boolean { + const secret = req.headers["x-webhook-secret"]; + return typeof secret === "string" && safeEqual(secret, app.ctx.config.WEBHOOK_SECRET); } -const KINDS: Record<"food" | "nonfood", VendorKind> = { - food: { ticketType: "Food Vendor", nameSlots: ["names", "names_1"] }, - nonfood: { ticketType: "Vendor", nameSlots: ["names"] }, -}; - -function makeHandler(app: FastifyInstance, kind: VendorKind) { +function foodHandler(app: FastifyInstance) { return async (req: any, reply: any) => { - const secret = req.headers["x-webhook-secret"]; - if (typeof secret !== "string" || !safeEqual(secret, app.ctx.config.WEBHOOK_SECRET)) { + if (!checkSecret(app, req)) { return reply.code(401).send({ error: "unauthorized" }); } @@ -42,7 +38,7 @@ function makeHandler(app: FastifyInstance, kind: VendorKind) { const boothName = String(body.input_text ?? "").trim(); // Pass-holder names (non-empty slots, in order). - const passHolders = kind.nameSlots.map((b) => nameGroup(body, b)).filter(Boolean); + const passHolders = FOOD_NAME_SLOTS.map((b) => nameGroup(body, b)).filter(Boolean); const primary = passHolders[0] ?? ""; // Ticket title = booth name (most useful at the gate), else the first person. const title = boothName || primary; @@ -63,7 +59,7 @@ function makeHandler(app: FastifyInstance, kind: VendorKind) { ? `sub:${String(submissionId)}` : "hash:" + createHash("sha256") - .update(`vendor|${kind.ticketType}|${email}|${title}|${passes}`) + .update(`vendor|Food Vendor|${email}|${title}|${passes}`) .digest("hex") .slice(0, 32); @@ -79,7 +75,7 @@ function makeHandler(app: FastifyInstance, kind: VendorKind) { address, isDonor, donorTier, - ticketType: kind.ticketType, + ticketType: "Food Vendor", counts, paymentMethod: body.payment_method !== undefined ? String(body.payment_method) : undefined, submissionKey, @@ -121,13 +117,25 @@ function makeHandler(app: FastifyInstance, kind: VendorKind) { }; } -export async function vendorWebhookRoutes(app: FastifyInstance): Promise { - // Configure these URLs in the two FluentForms vendor forms: - // Food: https://scan.beartariacampgrounds.com/vendor-webhook/food - // Non-Food: https://scan.beartariacampgrounds.com/vendor-webhook/non-food - app.post("/vendor-webhook/food", makeHandler(app, KINDS.food)); - app.post("/vendor-webhook/non-food", makeHandler(app, KINDS.nonfood)); - // Explicit API aliases. - app.post("/api/webhook/vendor-food", makeHandler(app, KINDS.food)); - app.post("/api/webhook/vendor-non-food", makeHandler(app, KINDS.nonfood)); +/** Non-food vendors don't get an entry ticket. Acknowledge and issue nothing + * (so a wired FluentForms feed doesn't error), but never create a ticket. */ +function nonFoodHandler(app: FastifyInstance) { + return async (req: any, reply: any) => { + if (!checkSecret(app, req)) { + return reply.code(401).send({ error: "unauthorized" }); + } + return { status: "ignored", reason: "non_food_no_ticket" }; + }; +} + +export async function vendorWebhookRoutes(app: FastifyInstance): Promise { + // Configure this URL in the FOOD vendor FluentForms form: + // https://scan.beartariacampgrounds.com/vendor-webhook/food + // Non-food vendors receive no entry ticket; the endpoint below is a safe + // no-op only so an accidentally-wired feed doesn't 404. + app.post("/vendor-webhook/food", foodHandler(app)); + app.post("/vendor-webhook/non-food", nonFoodHandler(app)); + // Explicit API aliases. + app.post("/api/webhook/vendor-food", foodHandler(app)); + app.post("/api/webhook/vendor-non-food", nonFoodHandler(app)); } diff --git a/backend/src/routes/webhookDoc.ts b/backend/src/routes/webhookDoc.ts index 276062b..b5c25cb 100644 --- a/backend/src/routes/webhookDoc.ts +++ b/backend/src/routes/webhookDoc.ts @@ -159,15 +159,15 @@ const PAGE = `

    Vendor booth webhooks

    -

    The two vendor forms on vendors.beartariacampgrounds.com post to their own endpoints (same X-Webhook-Secret). Each named booth person gets one entry pass; the booth name (input_text) becomes the ticket title, and the ticket is tagged with a vendor Ticket Type that shows a badge on scan and rolls up in the event report. Booth size / additional space are logistics and don't affect passes.

    +

    Only food vendors receive entry tickets. The vendor forms live on vendors.beartariacampgrounds.com and share the same X-Webhook-Secret. For a food booth, each named person gets one entry pass; the booth name (input_text) becomes the ticket title, and the ticket is tagged with a Food Vendor Ticket Type that shows a badge on scan and rolls up in the event report. Booth size / additional space are logistics and don't affect passes.

    - + - - + +
    FormEndpointPassesTicket Type
    FormEndpointResult
    Vendor Fee Food 2026POST /vendor-webhook/foodup to 2 (names + names_1)🍔 Food Vendor
    Vendor Fee Non-Food 2026POST /vendor-webhook/non-food1 (names)🛒 Vendor
    Vendor Fee Food 2026POST /vendor-webhook/food🍔 up to 2 passes (names + names_1), Food Vendor ticket + QR email
    Vendor Fee Non-Food 2026POST /vendor-webhook/non-foodNo ticket — acknowledged only ({"status":"ignored"}). You can leave this form's webhook unconfigured.
    -

    Relevant keys: input_text (Booth Name), names / names_1 (pass-holders), email, address_1, donor_tier / donor_eligible / input_radio (donor), payment_method. Same idempotency (id/submission_id) and response shapes as above, plus a passes count.

    +

    Relevant food keys: input_text (Booth Name), names / names_1 (pass-holders), email, address_1, donor_tier / donor_eligible / input_radio (donor), payment_method. Same idempotency (id/submission_id) and response shapes as above, plus a passes count.

    curl -X POST https://scan.beartariacampgrounds.com/vendor-webhook/food \\
       -H "Content-Type: application/json" \\
       -H "X-Webhook-Secret: <your WEBHOOK_SECRET>" \\
    diff --git a/backend/src/test/fluentforms.test.ts b/backend/src/test/fluentforms.test.ts
    index 4f21e4b..083f3b4 100644
    --- a/backend/src/test/fluentforms.test.ts
    +++ b/backend/src/test/fluentforms.test.ts
    @@ -1,11 +1,10 @@
     import { describe, it, expect } from "vitest";
     import { nameGroup, qty, selected, addressLine, readDonor } from "../fluentforms.js";
     
    -// Pass-holder name slots per the two vendor forms.
    +// Food vendors are the only vendor tickets; two pass-holder name slots.
     const FOOD_SLOTS = ["names", "names_1"];
    -const NONFOOD_SLOTS = ["names"];
     
    -/** Mirror the vendor handler's pass count: one per named person, min 1. */
    +/** Mirror the food vendor handler's pass count: one per named person, min 1. */
     function passCount(body: Record, slots: string[]): number {
       const holders = slots.map((b) => nameGroup(body, b)).filter(Boolean);
       return Math.max(1, holders.length);
    @@ -25,7 +24,7 @@ describe("nameGroup", () => {
       });
     });
     
    -describe("vendor pass counting", () => {
    +describe("food vendor pass counting", () => {
       it("food booth with two named holders gets 2 passes", () => {
         const body = {
           input_text: "Joe's Tacos",
    @@ -40,16 +39,6 @@ describe("vendor pass counting", () => {
         const body = { input_text: "Solo BBQ", "names[first_name]": "Sam", "names[last_name]": "Que" };
         expect(passCount(body, FOOD_SLOTS)).toBe(1);
       });
    -  it("non-food booth gets 1 pass (only one name slot)", () => {
    -    const body = {
    -      input_text: "Craft Corner",
    -      "names[first_name]": "Pat",
    -      "names[last_name]": "Maker",
    -      // a stray names_1 must NOT count for non-food
    -      "names_1[first_name]": "Ignore",
    -    };
    -    expect(passCount(body, NONFOOD_SLOTS)).toBe(1);
    -  });
       it("booth with no names still gets 1 pass", () => {
         expect(passCount({ input_text: "Nameless Booth" }, FOOD_SLOTS)).toBe(1);
       });
    
    From 1ba3f9ad1c675a9d79ed109a718bcacf1e0b4ee5 Mon Sep 17 00:00:00 2001
    From: Hank 
    Date: Thu, 16 Jul 2026 22:11:08 +0000
    Subject: [PATCH 11/22] Ticket vouchers now return remaining and decrement on
     use
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    The ticket-vouchers lookup previously returned the tier entitlement
    every time, so a donor could keep claiming free tickets by re-
    submitting the form. It now subtracts vouchers already consumed:
    
      remaining = entitled - used
    
    where `used` is the sum of the Vouchers column across that donor's
    prior ticket orders (each checkout stores what it applied). Response
    gains entitled/used/remaining; `vouchers` is now the remaining count
    the form should grant. Consumption is implicit — no counter to keep in
    sync — and resets by zeroing/deleting the Vouchers value on the order
    row in NocoDB.
    
    - nocodb: findByEmail + vouchersUsedByEmail (case-insensitive).
    - 8 new tests (36 total). Doc updated with the new response + reset.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) 
    ---
     backend/src/routes/publicLookup.ts  | 22 +++++++++++------
     backend/src/services/nocodb.ts      | 16 ++++++++++++
     backend/src/test/fakeNocodb.ts      | 11 +++++++++
     backend/src/test/vouchers.test.ts   | 38 +++++++++++++++++++++++++++++
     docs/fluentforms-ticket-vouchers.md | 27 +++++++++++++++-----
     5 files changed, 101 insertions(+), 13 deletions(-)
     create mode 100644 backend/src/test/vouchers.test.ts
    
    diff --git a/backend/src/routes/publicLookup.ts b/backend/src/routes/publicLookup.ts
    index d1437f9..998a7fb 100644
    --- a/backend/src/routes/publicLookup.ts
    +++ b/backend/src/routes/publicLookup.ts
    @@ -69,9 +69,15 @@ export async function publicLookupRoutes(app: FastifyInstance): Promise {
         },
       );
     
    -  // Ticket-voucher entitlement: how many free tickets a donor has earned from
    -  // giving on/after VOUCHER_SINCE. Same secret/CORS/rate-limit as above.
    -  // Returns only the count (0/1/2) — no dollar amounts.
    +  // Ticket-voucher entitlement: how many FREE tickets a donor has left. This is
    +  // the tier entitlement earned from giving on/after VOUCHER_SINCE, MINUS the
    +  // vouchers already consumed by their prior ticket orders (each order stores
    +  // how many it used), so a donor can't keep claiming free tickets by
    +  // re-submitting the form. `vouchers` is the remaining count the form should
    +  // grant; `entitled`/`used`/`remaining` are the breakdown. No dollar amounts.
    +  //
    +  // To reset for testing: zero out (or delete) the "Vouchers" value on that
    +  // donor's ticket order row(s) in NocoDB — `used` drops and `remaining` rises.
       app.get(
         "/api/public/ticket-vouchers",
         { config: { rateLimit: { max: 30, timeWindow: "1 minute" } } },
    @@ -85,16 +91,18 @@ export async function publicLookupRoutes(app: FastifyInstance): Promise {
           }
           const { email } = (req.query ?? {}) as { email?: string };
           const addr = String(email ?? "").trim();
    -      if (!addr) return { vouchers: 0 };
    +      if (!addr) return { vouchers: 0, entitled: 0, used: 0, remaining: 0 };
     
           try {
             const cutoff = new Date(cfg.VOUCHER_SINCE);
             const { amount } = await app.ctx.donors.amountSince(addr, cutoff);
    -        const vouchers = amount >= cfg.VOUCHER_TIER2_MIN ? 2 : amount >= cfg.VOUCHER_TIER1_MIN ? 1 : 0;
    -        return { vouchers };
    +        const entitled = amount >= cfg.VOUCHER_TIER2_MIN ? 2 : amount >= cfg.VOUCHER_TIER1_MIN ? 1 : 0;
    +        const used = await app.ctx.nocodb.vouchersUsedByEmail(addr);
    +        const remaining = Math.max(0, entitled - used);
    +        return { vouchers: remaining, entitled, used, remaining };
           } catch {
             // Fail closed — grant no vouchers rather than error.
    -        return { vouchers: 0 };
    +        return { vouchers: 0, entitled: 0, used: 0, remaining: 0 };
           }
         },
       );
    diff --git a/backend/src/services/nocodb.ts b/backend/src/services/nocodb.ts
    index a9f8587..f26f452 100644
    --- a/backend/src/services/nocodb.ts
    +++ b/backend/src/services/nocodb.ts
    @@ -76,6 +76,22 @@ export class NocoDBClient {
         return this.list(`(${COL.name},like,%${q}%)~or(${COL.email},like,%${q}%)`, limit);
       }
     
    +  /** Every order for an exact email (case-insensitive). */
    +  async findByEmail(email: string, limit = 1000): Promise {
    +    const rows = await this.list(`(${COL.email},eq,${escapeValue(email)})`, limit);
    +    // Belt-and-suspenders: some NocoDB backends do a case-sensitive eq, so
    +    // narrow/confirm against a lowercased compare in JS.
    +    const target = email.trim().toLowerCase();
    +    const exact = rows.filter((r) => String(r[COL.email] ?? "").trim().toLowerCase() === target);
    +    return exact.length ? exact : rows;
    +  }
    +
    +  /** Sum of ticket vouchers a donor has already consumed across their orders. */
    +  async vouchersUsedByEmail(email: string): Promise {
    +    const rows = await this.findByEmail(email);
    +    return rows.reduce((sum, r) => sum + (Number(r[COL.vouchers]) || 0), 0);
    +  }
    +
       async create(fields: Record): Promise {
         const body = await this.request(this.recordsUrl, {
           method: "POST",
    diff --git a/backend/src/test/fakeNocodb.ts b/backend/src/test/fakeNocodb.ts
    index 9a158f8..d8fe66b 100644
    --- a/backend/src/test/fakeNocodb.ts
    +++ b/backend/src/test/fakeNocodb.ts
    @@ -41,6 +41,17 @@ export class FakeNocoDB {
         );
       }
     
    +  async findByEmail(email: string): Promise {
    +    await this.delay();
    +    const target = email.trim().toLowerCase();
    +    return this.rows.filter((r) => String(r[COL.email] ?? "").trim().toLowerCase() === target);
    +  }
    +
    +  async vouchersUsedByEmail(email: string): Promise {
    +    const rows = await this.findByEmail(email);
    +    return rows.reduce((sum, r) => sum + (Number(r[COL.vouchers]) || 0), 0);
    +  }
    +
       async create(fields: Record): Promise {
         await this.delay();
         const rec = { Id: this.nextId++, ...fields } as NocoRecord;
    diff --git a/backend/src/test/vouchers.test.ts b/backend/src/test/vouchers.test.ts
    new file mode 100644
    index 0000000..497887a
    --- /dev/null
    +++ b/backend/src/test/vouchers.test.ts
    @@ -0,0 +1,38 @@
    +import { describe, it, expect } from "vitest";
    +import { FakeNocoDB } from "./fakeNocodb.js";
    +import { COL } from "../fields.js";
    +
    +/** Mirror the ticket-vouchers endpoint's remaining math. */
    +function remaining(entitled: number, used: number): number {
    +  return Math.max(0, entitled - used);
    +}
    +
    +describe("voucher consumption", () => {
    +  it("sums vouchers used across a donor's orders", async () => {
    +    const db = new FakeNocoDB(0);
    +    await db.create({ [COL.email]: "donor@example.com", [COL.vouchers]: 2 });
    +    await db.create({ [COL.email]: "donor@example.com", [COL.vouchers]: 1 });
    +    await db.create({ [COL.email]: "someone-else@example.com", [COL.vouchers]: 2 });
    +    await db.create({ [COL.email]: "donor@example.com", [COL.vouchers]: 0 }); // non-voucher order
    +    expect(await db.vouchersUsedByEmail("donor@example.com")).toBe(3);
    +  });
    +
    +  it("matches email case-insensitively", async () => {
    +    const db = new FakeNocoDB(0);
    +    await db.create({ [COL.email]: "Donor@Example.com", [COL.vouchers]: 2 });
    +    expect(await db.vouchersUsedByEmail("donor@example.com")).toBe(2);
    +  });
    +
    +  it("returns 0 used for a donor with no orders", async () => {
    +    const db = new FakeNocoDB(0);
    +    expect(await db.vouchersUsedByEmail("nobody@example.com")).toBe(0);
    +  });
    +
    +  it("remaining = entitled - used, floored at 0", () => {
    +    expect(remaining(2, 0)).toBe(2); // fresh 2-voucher donor
    +    expect(remaining(2, 1)).toBe(1); // used one
    +    expect(remaining(2, 2)).toBe(0); // used both — no more free tickets
    +    expect(remaining(1, 2)).toBe(0); // over-consumed (edge) never goes negative
    +    expect(remaining(0, 0)).toBe(0); // non-donor
    +  });
    +});
    diff --git a/docs/fluentforms-ticket-vouchers.md b/docs/fluentforms-ticket-vouchers.md
    index 6f079a5..af66c45 100644
    --- a/docs/fluentforms-ticket-vouchers.md
    +++ b/docs/fluentforms-ticket-vouchers.md
    @@ -14,16 +14,32 @@ ticketing backend.
     GET https://scan.beartariacampgrounds.com/api/public/ticket-vouchers?key=&email=
     ```
     
    -Returns only the count — never names or dollar amounts:
    +Returns the **remaining** free-ticket count — never names or dollar amounts:
     
     ```json
    -{ "vouchers": 0 }   // or 1, or 2
    +{ "vouchers": 1, "entitled": 2, "used": 1, "remaining": 1 }
     ```
     
    +- `vouchers` / `remaining` — how many free tickets are **still available** (this
    +  is what the form should grant). Use `vouchers`; `remaining` is an alias.
    +- `entitled` — the tier entitlement earned from giving (0/1/2).
    +- `used` — vouchers already consumed by this donor's prior ticket orders.
     - `key` = the value of `PUBLIC_LOOKUP_SECRET` (set in the backend `.env`).
     - `email` = the donor's email (URL-encoded).
     - Rate-limited (30 requests / minute / IP) and CORS-restricted to
    -  `PUBLIC_LOOKUP_ORIGIN` (default `https://tickets.beartariacampgrounds.com`).
    +  `PUBLIC_LOOKUP_ORIGIN` (`tickets.` + `vendors.beartariacampgrounds.com`).
    +
    +### Vouchers decrement as they're used
    +
    +`remaining = entitled − used`, where `used` is the sum of the **Vouchers**
    +column across every ticket order placed with that email. Each checkout stores
    +the vouchers it applied, so the next lookup returns fewer — a donor can't keep
    +claiming free tickets by re-submitting the form. Once `used ≥ entitled`,
    +`vouchers` is `0`.
    +
    +**To reset for testing:** in NocoDB, zero out (or delete) the **Vouchers**
    +value on that donor's ticket order row(s). `used` drops and `remaining` rises on
    +the next lookup — no redeploy needed.
     
     > The secret is visible in page source, so treat it as **deterrence, not
     > security** — it only gates a 0/1/2 count. Rotate it by changing
    @@ -107,9 +123,8 @@ field `free_tickets` you can use for conditional logic or to cap a quantity.
     
     ```
     curl "https://scan.beartariacampgrounds.com/api/public/ticket-vouchers?key=&email="
    -# >= $1000 since cutoff -> {"vouchers":2}
    -# >= $400  since cutoff -> {"vouchers":1}
    -# otherwise             -> {"vouchers":0}
    +# entitled 2, none used yet -> {"vouchers":2,"entitled":2,"used":0,"remaining":2}
    +# after a checkout using 2  -> {"vouchers":0,"entitled":2,"used":2,"remaining":0}
     ```
     
     Related: [`fluentforms-donor-discount.md`](./fluentforms-donor-discount.md) — the
    
    From e86651723d5c793acf301d9a09a49c3c0d069587 Mon Sep 17 00:00:00 2001
    From: Hank 
    Date: Fri, 17 Jul 2026 04:33:21 +0000
    Subject: [PATCH 12/22] Webhook: capture donor adult ticket names (Tickets 2026
     update)
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    The updated Tickets 2026 form adds two donor (voucher) adult-ticket
    name groups, names_Donor_1 / names_Donor_2, for the free adult
    admissions. These were already counted via
    item_quantity_adult_ticket_donor but their attendee names weren't
    captured — added them to the adult-name list so they show at the gate.
    Doc updated (new name fields + note that pure pricing line items and
    payment_donor_voucher1/2 are ignored; the vouchers hidden count is
    authoritative). No other schema changes needed — counts, extras,
    donor, ice, and voucher handling already matched.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) 
    ---
     backend/src/routes/webhook.ts    | 11 +++++++++--
     backend/src/routes/webhookDoc.ts |  3 ++-
     2 files changed, 11 insertions(+), 3 deletions(-)
    
    diff --git a/backend/src/routes/webhook.ts b/backend/src/routes/webhook.ts
    index 77d7522..08df9e0 100644
    --- a/backend/src/routes/webhook.ts
    +++ b/backend/src/routes/webhook.ts
    @@ -5,8 +5,15 @@ import { createTicket } from "../ticketService.js";
     import { renderQrPng } from "../services/qrcode.js";
     import { safeEqual, nameGroup, qty, selected, addressLine } from "../fluentforms.js";
     
    -// Adult name field bases, in order (purchaser first).
    -const ADULT_NAME_BASES = ["names", "names_1", "names_2", "names_3", "names_4", "names_5", "names_6", "names_7", "names_8", "names_9"];
    +// Adult name field bases, in order: purchaser first, then additional regular
    +// adults (Adult Ticket #2–#10), then donor adult tickets (Adult Donor #1–#2).
    +// Donor tickets are the free/voucher adult admissions; their names live in the
    +// separate names_Donor_* groups but are still adults who need a gate pass.
    +const ADULT_NAME_BASES = [
    +  "names",
    +  "names_1", "names_2", "names_3", "names_4", "names_5", "names_6", "names_7", "names_8", "names_9",
    +  "names_Donor_1", "names_Donor_2",
    +];
     
     export async function webhookRoutes(app: FastifyInstance): Promise {
       const handler = async (req: any, reply: any) => {
    diff --git a/backend/src/routes/webhookDoc.ts b/backend/src/routes/webhookDoc.ts
    index b5c25cb..b9930fb 100644
    --- a/backend/src/routes/webhookDoc.ts
    +++ b/backend/src/routes/webhookDoc.ts
    @@ -13,6 +13,7 @@ interface Field {
     const FIELDS: Field[] = [
       { key: "names", req: "required", type: "name (compound)", desc: "Purchaser / Adult #1 — object {first_name, middle_name, last_name}. Also accepts flat names[first_name] keys." },
       { key: "names_1 … names_9", req: "optional", type: "name (compound)", desc: "Additional adult attendee names (Adults #2–#10). Empty groups are ignored. Stored as the adult-name list shown at the gate." },
    +  { key: "names_Donor_1 / names_Donor_2", req: "optional", type: "name (compound)", desc: "Donor (voucher) adult ticket names — the free adult admissions. Counted via item_quantity_adult_ticket_donor and added to the gate name list." },
       { key: "email", req: "optional", type: "email", desc: "Purchaser email — the QR ticket is sent here (FluentForms sends the receipt separately)." },
       { key: "address_1", req: "optional", type: "address (compound)", desc: "Mailing address object; joined into one line." },
       { key: "item_quantity_adult_ticket_reg", req: "required", type: "quantity", desc: "Adult tickets (regular)." },
    @@ -125,7 +126,7 @@ const PAGE = `
           KeyRequiredTypeDescription
           ${rows}
         
    -    

    Compound name fields arrive as objects (names: {first_name,…}) or flattened names[first_name] keys — both handled. Quantity/payment fields accept numbers, money strings ("$40.00"), or {quantity} objects.

    +

    Compound name fields arrive as objects (names: {first_name,…}) or flattened names[first_name] keys — both handled. Quantity/payment fields accept numbers, money strings ("$40.00"), or {quantity} objects. Counts come from the item_quantity_* fields, so pure pricing line items (payment_adult_reg, payment_youth_*, payment_kids_free, payment_donor_voucher1/2, custom-payment-amount/Tax) are ignored — the vouchers hidden count is authoritative for donor vouchers.

    Idempotency

    Send a stable id / submission_id. A repeat returns {"status":"duplicate"} without creating a second ticket or re-emailing — safe for retries and double-submits.

    From a987e046dae040c1f7712bcccdb85c23dc7e5f04 Mon Sep 17 00:00:00 2001 From: Hank Date: Fri, 17 Jul 2026 17:59:56 +0000 Subject: [PATCH 13/22] Webhook: customer_name purchaser + allow ticketless orders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two fixes for the updated Tickets 2026 form: 1. Purchaser name now comes from the new customer_name (billing) field, falling back to the first attendee then a plain `name`. Donor-only and buy-for-others orders (where the Adult #1 `names` group is empty) no longer 400 with "purchaser name is required". The ticket title is the first attendee if present, else the customer; the QR email is addressed to the customer. 2. Tickets are now optional. A customer can buy ice / ATV-UTV / parking with no admission ticket. A record + QR is created whenever there's anything to redeem or verify at the gate (ticket, ice, or add-on); only a truly empty order is rejected (no_items, replacing no_tickets). The ticket email adapts its copy for ticketless (add-on-only) orders — it reads as a gate pass for ice/parking/UTV instead of "0 tickets", and names the ice bag count when present. Idempotency hash now includes ice/extras so distinct add-on-only orders don't collide. Doc updated. Co-Authored-By: Claude Opus 4.8 (1M context) --- backend/src/routes/webhook.ts | 40 ++++++++++++++--------- backend/src/routes/webhookDoc.ts | 8 +++-- backend/src/services/mailer.ts | 54 +++++++++++++++++++++++++------- 3 files changed, 74 insertions(+), 28 deletions(-) diff --git a/backend/src/routes/webhook.ts b/backend/src/routes/webhook.ts index 08df9e0..3cf3347 100644 --- a/backend/src/routes/webhook.ts +++ b/backend/src/routes/webhook.ts @@ -24,15 +24,19 @@ export async function webhookRoutes(app: FastifyInstance): Promise { const body = (req.body ?? {}) as Record; - // Purchaser = the first adult name group; fall back to a plain `name` field. - const name = nameGroup(body, "names") || String(body.name ?? "").trim(); const email = String(body.email ?? "").trim(); - if (!name) { - return reply.code(400).send({ error: "missing_fields", detail: "purchaser name is required" }); - } - // Adult attendee names (non-empty groups, in order). + // Billing/customer name (the purchaser — may differ from attendees, e.g. + // buying for others or add-ons only) + the attendee name groups. + const customerName = nameGroup(body, "customer_name") || String(body.name ?? "").trim(); const adultNames = ADULT_NAME_BASES.map((b) => nameGroup(body, b)).filter(Boolean); + // Person the email is addressed to (the buyer). + const purchaser = customerName || adultNames[0]; + // Title shown at the gate: the first attendee if any, else the customer. + const title = adultNames[0] || customerName; + if (!title) { + return reply.code(400).send({ error: "missing_fields", detail: "customer or attendee name is required" }); + } // Attendee counts. const counts = { @@ -45,11 +49,6 @@ export async function webhookRoutes(app: FastifyInstance): Promise { // Paid/scannable admissions = adults + youth 13-16. Children 12 & under are // free (charging starts at 13) and are stored but not counted at the gate. const scannable = counts.adults + counts.youth; - if (scannable <= 0) { - // Nothing to check in at the gate. Log the payload so we can calibrate. - req.log.warn({ body }, "webhook: no scannable tickets in submission"); - return reply.code(400).send({ error: "no_tickets", detail: "no paid tickets (adults / youth 13-16)" }); - } // Donor info (hidden fields from the eligibility/voucher lookups) + radio. const donorTier = String(body.donor_tier ?? "").trim(); @@ -71,22 +70,32 @@ export async function webhookRoutes(app: FastifyInstance): Promise { const iceBags = Math.max(0, iceTickets) * app.ctx.config.ICE_BAGS_PER_TICKET; const iceAccess = iceBags > 0 || selected(body.input_radio_7); + // Tickets are optional: a customer can buy ice/UTV/parking with no admission + // ticket, or buy tickets for others. Only reject a truly empty order — + // nothing to check in, redeem, or verify at the gate. + const hasIssuable = scannable > 0 || iceBags > 0 || utv || carParking || rvParking; + if (!hasIssuable) { + req.log.warn({ body }, "webhook: submission has nothing to issue"); + return reply.code(400).send({ error: "no_items", detail: "no tickets, ice, or add-ons in submission" }); + } + const address = addressLine(body.address_1); - // Idempotency: prefer a stable submission id, else hash the content. + // Idempotency: prefer a stable submission id, else hash the content + // (include ice/extras so distinct add-on-only orders don't collide). const submissionId = body.submission_id ?? body.submissionId ?? body.entry_id ?? body.id; const submissionKey = submissionId ? `sub:${String(submissionId)}` : "hash:" + createHash("sha256") - .update(`${email}|${name}|${JSON.stringify(counts)}`) + .update(`${email}|${title}|${JSON.stringify(counts)}|${iceBags}|${carParking}|${rvParking}|${utv}`) .digest("hex") .slice(0, 32); let result: Awaited>; try { result = await createTicket(app.ctx, { - name, + name: title, adultNames, email, address, @@ -127,10 +136,11 @@ export async function webhookRoutes(app: FastifyInstance): Promise { const qr = await renderQrPng(result.code); await app.ctx.mailer.sendTicket({ toEmail: email, - toName: name, + toName: purchaser, code: result.code, quantity: scannable, qrPng: qr, + iceBags, }); } catch (e: any) { req.log.error({ err: e, code: result.code }, "webhook: ticket created but email failed"); diff --git a/backend/src/routes/webhookDoc.ts b/backend/src/routes/webhookDoc.ts index b9930fb..ea5f10a 100644 --- a/backend/src/routes/webhookDoc.ts +++ b/backend/src/routes/webhookDoc.ts @@ -11,7 +11,8 @@ interface Field { } const FIELDS: Field[] = [ - { key: "names", req: "required", type: "name (compound)", desc: "Purchaser / Adult #1 — object {first_name, middle_name, last_name}. Also accepts flat names[first_name] keys." }, + { key: "customer_name", req: "required", type: "name (compound)", desc: "Billing / customer name — the buyer. Used to address the email and as the ticket title when there are no attendee names (add-on-only orders). Object {first_name, middle_name, last_name}; flat customer_name[first_name] keys also accepted." }, + { key: "names", req: "optional", type: "name (compound)", desc: "Adult Ticket #1 attendee — object {first_name, middle_name, last_name}. Also accepts flat names[first_name] keys. May be empty when buying only donor tickets or add-ons." }, { key: "names_1 … names_9", req: "optional", type: "name (compound)", desc: "Additional adult attendee names (Adults #2–#10). Empty groups are ignored. Stored as the adult-name list shown at the gate." }, { key: "names_Donor_1 / names_Donor_2", req: "optional", type: "name (compound)", desc: "Donor (voucher) adult ticket names — the free adult admissions. Counted via item_quantity_adult_ticket_donor and added to the gate name list." }, { key: "email", req: "optional", type: "email", desc: "Purchaser email — the QR ticket is sent here (FluentForms sends the receipt separately)." }, @@ -55,6 +56,7 @@ const rows = FIELDS.map( const exampleJson = esc(`{ "id": "412", + "customer_name": { "first_name": "Jane", "last_name": "Bear" }, "names": { "first_name": "Jane", "last_name": "Bear" }, "names_1": { "first_name": "John", "last_name": "Bear" }, "email": "jane@example.com", @@ -120,6 +122,7 @@ const PAGE = `

    What it does

    On a valid request the backend generates a unique ticket code, creates a NocoDB row, and emails the QR code to the purchaser (subject "2026 Beartaria Campgrounds Tickets"). FluentForms sends the payment receipt separately.

    Scannable ticket total = adults + youth (13-16). Children 12 & under are free (charging starts at 13) — their counts are stored and shown to gate staff, but not counted toward the ticket total. Each adult name provided is stored and shown on a successful scan.

    +

    Tickets are optional. A customer can buy ice, an ATV/UTV pass, or parking with no admission ticket, or buy tickets for other people. A record + QR is still created as long as there's something to redeem or verify at the gate (a ticket, ice, or an add-on). Only a truly empty order is rejected.

    Fields

    @@ -144,7 +147,8 @@ const PAGE = ` - + + diff --git a/backend/src/services/mailer.ts b/backend/src/services/mailer.ts index a27ce84..a97f10b 100644 --- a/backend/src/services/mailer.ts +++ b/backend/src/services/mailer.ts @@ -9,6 +9,43 @@ export interface TicketEmail { code: string; quantity: number; qrPng: Buffer; + iceBags?: number; // for add-on-only (ticketless) orders +} + +/** Describe what a purchase is good for — handles ticketless (ice/UTV) orders. */ +function purchaseSummary(mail: TicketEmail): { lead: string; footer: string } { + const qty = mail.quantity; + if (qty > 0) { + const w = qty === 1 ? "ticket" : "tickets"; + return { + lead: `This email is your ticket for ${qty} ${w} to the 2026 Beartaria Campgrounds event. Show the QR code below at the gate.`, + footer: `Each ticket admits one entry. This code is good for all ${qty} ${w} on one purchase — gate staff will check people in against it. See you there!`, + }; + } + const bags = mail.iceBags ?? 0; + const extra = bags > 0 ? ` It includes ${bags} bag${bags === 1 ? "" : "s"} of ice.` : ""; + return { + lead: `This email is your gate pass for your 2026 Beartaria Campgrounds purchase (add-ons such as ice, parking, or an ATV/UTV).${extra} Show the QR code below at the gate.`, + footer: `Show this QR at the gate and staff will redeem your add-ons against it. See you there!`, + }; +} + +/** Plain-text version of purchaseSummary (no HTML tags). */ +function purchaseSummaryText(mail: TicketEmail): { lead: string; footer: string } { + const qty = mail.quantity; + if (qty > 0) { + const w = qty === 1 ? "ticket" : "tickets"; + return { + lead: `This is your ticket for ${qty} ${w} to the 2026 Beartaria Campgrounds event.`, + footer: `It is good for all ${qty} ${w} on this purchase.`, + }; + } + const bags = mail.iceBags ?? 0; + const extra = bags > 0 ? ` It includes ${bags} bag${bags === 1 ? "" : "s"} of ice.` : ""; + return { + lead: `This is your gate pass for your purchase (add-ons such as ice, parking, or an ATV/UTV).${extra}`, + footer: `Show this code at the gate and staff will redeem your add-ons against it.`, + }; } export class MailerSendError extends Error { @@ -94,8 +131,7 @@ function esc(s: string): string { function renderHtml(mail: TicketEmail): string { const name = esc(mail.toName || ""); - const qty = mail.quantity; - const ticketWord = qty === 1 ? "ticket" : "tickets"; + const { lead, footer } = purchaseSummary(mail); return ` @@ -108,9 +144,7 @@ function renderHtml(mail: TicketEmail): string {
    200{"status":"created","code":"BC26-…","emailSent":true}Ticket created and emailed.
    200{"status":"duplicate","code":"BC26-…"}Same submission already processed — no-op.
    400{"error":"missing_fields"} / "no_tickets"Missing purchaser name, or zero scannable tickets.
    400{"error":"missing_fields"}No customer name and no attendee names.
    400{"error":"no_items"}Empty order — no tickets, ice, or add-ons.
    401{"error":"unauthorized"}Missing or wrong X-Webhook-Secret.
    502{"status":"created","emailSent":false,…}Ticket row created but the email failed — re-send from the admin app.

    Hi ${name || "there"},

    - Thank you for your purchase! This email is your ticket for - ${qty} ${ticketWord} to the 2026 Beartaria Campgrounds event. - Show the QR code below at the gate. + Thank you for your purchase! ${lead}

    Ticket QR code

    - Each ticket admits one entry. This code is good for all ${qty} ${ticketWord} on one purchase — - gate staff will check people in against it. See you there! + ${footer}

    @@ -134,17 +167,16 @@ function renderHtml(mail: TicketEmail): string { } function renderText(mail: TicketEmail): string { - const qty = mail.quantity; - const ticketWord = qty === 1 ? "ticket" : "tickets"; + const { lead, footer } = purchaseSummaryText(mail); return [ `Hi ${mail.toName || "there"},`, "", - `Thank you for your purchase! This is your ticket for ${qty} ${ticketWord} to the 2026 Beartaria Campgrounds event.`, + `Thank you for your purchase! ${lead}`, "", `Your ticket code: ${mail.code}`, "", "Show this code (or the QR code in the HTML version of this email) at the gate.", - `It is good for all ${qty} ${ticketWord} on this purchase.`, + footer, "", "See you there!", "Beartaria Campgrounds · beartariacampgrounds.com", From 49e45ff94c780498067bbbc1e0e4bdd9d0defc61 Mon Sep 17 00:00:00 2001 From: Hank Date: Fri, 17 Jul 2026 19:07:56 +0000 Subject: [PATCH 14/22] Webhook: count voucher tickets + use customer_name as title MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two corrections to the adult-ticket model: 1. Adult total was undercounting. Voucher (donor) tickets live only in the names_Donor_1 / names_Donor_2 name fields — each filled name is one free voucher adult ticket — and weren't counted at all. Adults now = item_quantity_adult_ticket_reg (regular) + item_quantity_adult_ticket_donor (extra PAID donor tickets beyond vouchers) + the donor voucher-name count. Vouchers consumed is now that same donor-name count (what the ticket-voucher lookup subtracts), instead of the hidden `vouchers` entitlement. 2. Ticket title now comes from customer_name (billing name), not the first adult ticket name. Doc updated to describe the adult total and the title source. Co-Authored-By: Claude Opus 4.8 (1M context) --- backend/src/routes/webhook.ts | 34 +++++++++++++++++++++----------- backend/src/routes/webhookDoc.ts | 14 ++++++------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/backend/src/routes/webhook.ts b/backend/src/routes/webhook.ts index 3cf3347..7f5595d 100644 --- a/backend/src/routes/webhook.ts +++ b/backend/src/routes/webhook.ts @@ -5,15 +5,17 @@ import { createTicket } from "../ticketService.js"; import { renderQrPng } from "../services/qrcode.js"; import { safeEqual, nameGroup, qty, selected, addressLine } from "../fluentforms.js"; -// Adult name field bases, in order: purchaser first, then additional regular -// adults (Adult Ticket #2–#10), then donor adult tickets (Adult Donor #1–#2). -// Donor tickets are the free/voucher adult admissions; their names live in the -// separate names_Donor_* groups but are still adults who need a gate pass. -const ADULT_NAME_BASES = [ +// Regular adult attendee name groups (Adult Ticket #1–#10), in order. +const REGULAR_NAME_BASES = [ "names", "names_1", "names_2", "names_3", "names_4", "names_5", "names_6", "names_7", "names_8", "names_9", - "names_Donor_1", "names_Donor_2", ]; +// Donor voucher ticket name groups. Each FILLED group is one free voucher adult +// ticket — the voucher tickets live in these two name fields (there's no +// separate quantity field for them). +const DONOR_NAME_BASES = ["names_Donor_1", "names_Donor_2"]; +// All adult names for the gate display list. +const ADULT_NAME_BASES = [...REGULAR_NAME_BASES, ...DONOR_NAME_BASES]; export async function webhookRoutes(app: FastifyInstance): Promise { const handler = async (req: any, reply: any) => { @@ -30,17 +32,23 @@ export async function webhookRoutes(app: FastifyInstance): Promise { // buying for others or add-ons only) + the attendee name groups. const customerName = nameGroup(body, "customer_name") || String(body.name ?? "").trim(); const adultNames = ADULT_NAME_BASES.map((b) => nameGroup(body, b)).filter(Boolean); - // Person the email is addressed to (the buyer). + // Free voucher adult tickets = number of donor name fields filled. + const voucherTickets = DONOR_NAME_BASES.map((b) => nameGroup(body, b)).filter(Boolean).length; + // Ticket title + email recipient = the billing/customer name (fall back to + // the first attendee only if the customer name is somehow missing). const purchaser = customerName || adultNames[0]; - // Title shown at the gate: the first attendee if any, else the customer. - const title = adultNames[0] || customerName; + const title = customerName || adultNames[0]; if (!title) { return reply.code(400).send({ error: "missing_fields", detail: "customer or attendee name is required" }); } - // Attendee counts. + // Attendee counts. Adults = regular (paid) tickets + additional paid donor + // tickets + free voucher tickets (one per donor name provided). const counts = { - adults: qty(body.item_quantity_adult_ticket_reg) + qty(body.item_quantity_adult_ticket_donor), + adults: + qty(body.item_quantity_adult_ticket_reg) + + qty(body.item_quantity_adult_ticket_donor) + + voucherTickets, youth: qty(body.item_quantity_youth_ticket_reg) + qty(body.item_quantity_youth_ticket_donor), kids12: qty(body.item_quantity_kids_12), kids9: qty(body.item_quantity_kids_9), @@ -57,7 +65,9 @@ export async function webhookRoutes(app: FastifyInstance): Promise { donorTier === "donor" || toBool(body.donor_eligible) || selected(body.input_radio); // "Are you a campground donor?" - const vouchers = qty(body.vouchers); + // Vouchers consumed in this order = the free voucher tickets actually taken + // (donor names filled), which is what the ticket-voucher lookup subtracts. + const vouchers = voucherTickets; // Extras (best-effort from payment fields — donor variants may be free/$0). const carParking = selected(body.payment_parking_reg) || selected(body.payment_parking_donor); diff --git a/backend/src/routes/webhookDoc.ts b/backend/src/routes/webhookDoc.ts index ea5f10a..c2a146c 100644 --- a/backend/src/routes/webhookDoc.ts +++ b/backend/src/routes/webhookDoc.ts @@ -11,21 +11,21 @@ interface Field { } const FIELDS: Field[] = [ - { key: "customer_name", req: "required", type: "name (compound)", desc: "Billing / customer name — the buyer. Used to address the email and as the ticket title when there are no attendee names (add-on-only orders). Object {first_name, middle_name, last_name}; flat customer_name[first_name] keys also accepted." }, + { key: "customer_name", req: "required", type: "name (compound)", desc: "Billing / customer name — the buyer. Stored as the ticket title and used to address the email. Object {first_name, middle_name, last_name}; flat customer_name[first_name] keys also accepted." }, { key: "names", req: "optional", type: "name (compound)", desc: "Adult Ticket #1 attendee — object {first_name, middle_name, last_name}. Also accepts flat names[first_name] keys. May be empty when buying only donor tickets or add-ons." }, - { key: "names_1 … names_9", req: "optional", type: "name (compound)", desc: "Additional adult attendee names (Adults #2–#10). Empty groups are ignored. Stored as the adult-name list shown at the gate." }, - { key: "names_Donor_1 / names_Donor_2", req: "optional", type: "name (compound)", desc: "Donor (voucher) adult ticket names — the free adult admissions. Counted via item_quantity_adult_ticket_donor and added to the gate name list." }, + { key: "names_1 … names_9", req: "optional", type: "name (compound)", desc: "Additional regular adult attendee names (Adults #2–#10). Empty groups are ignored. Stored as the adult-name list shown at the gate." }, + { key: "names_Donor_1 / names_Donor_2", req: "optional", type: "name (compound)", desc: "Donor voucher ticket names. Each FILLED group is one FREE voucher adult ticket — this is how voucher tickets are counted (there's no quantity field for them). Also added to the gate name list and recorded as the vouchers consumed." }, { key: "email", req: "optional", type: "email", desc: "Purchaser email — the QR ticket is sent here (FluentForms sends the receipt separately)." }, { key: "address_1", req: "optional", type: "address (compound)", desc: "Mailing address object; joined into one line." }, - { key: "item_quantity_adult_ticket_reg", req: "required", type: "quantity", desc: "Adult tickets (regular)." }, - { key: "item_quantity_adult_ticket_donor", req: "required", type: "quantity", desc: "Adult tickets (donor). Added to the regular adults." }, + { key: "item_quantity_adult_ticket_reg", req: "required", type: "quantity", desc: "Regular (non-donor) adult tickets." }, + { key: "item_quantity_adult_ticket_donor", req: "required", type: "quantity", desc: "ADDITIONAL paid donor adult tickets bought beyond the free vouchers. Added to the adult total; does NOT include the voucher tickets (those come from names_Donor_1/2)." }, { key: "item_quantity_youth_ticket_reg / _donor", req: "optional", type: "quantity", desc: "Youth 13-16 tickets (regular + donor)." }, { key: "item_quantity_kids_12", req: "optional", type: "quantity", desc: "Kids 10-12. FREE — stored but NOT counted toward the scannable ticket total." }, { key: "item_quantity_kids_9", req: "optional", type: "quantity", desc: "Kids 5-9. FREE — stored but NOT counted toward the scannable ticket total." }, { key: "item_quantity_kids_4", req: "optional", type: "quantity", desc: "Kids 0-4. FREE — stored but NOT counted toward the scannable ticket total." }, { key: "donor_tier", req: "optional", type: "hidden", desc: "member / donor / empty (from the donor-eligibility lookup)." }, { key: "donor_eligible", req: "optional", type: "hidden", desc: "true / false (from the donor-eligibility lookup)." }, - { key: "vouchers", req: "optional", type: "hidden", desc: "Integer voucher count (from the ticket-voucher lookup)." }, + { key: "vouchers", req: "optional", type: "hidden", desc: "Voucher entitlement from the ticket-voucher lookup (informational). The vouchers actually consumed are counted from the filled names_Donor_1/2 groups, not this field." }, { key: "input_radio", req: "optional", type: "choice", desc: "'Are you a campground donor?' — also used as a donor signal." }, { key: "payment_parking_reg / _donor", req: "optional", type: "payment", desc: "Car parking. Flagged if either variant is selected." }, { key: "payment_rv_reg / _donor", req: "optional", type: "payment", desc: "RV. Flagged if either variant is selected." }, @@ -121,7 +121,7 @@ const PAGE = `

    What it does

    On a valid request the backend generates a unique ticket code, creates a NocoDB row, and emails the QR code to the purchaser (subject "2026 Beartaria Campgrounds Tickets"). FluentForms sends the payment receipt separately.

    -

    Scannable ticket total = adults + youth (13-16). Children 12 & under are free (charging starts at 13) — their counts are stored and shown to gate staff, but not counted toward the ticket total. Each adult name provided is stored and shown on a successful scan.

    +

    Scannable ticket total = adults + youth (13-16). Adults = item_quantity_adult_ticket_reg (regular) + item_quantity_adult_ticket_donor (extra paid donor tickets) + the number of donor voucher names (names_Donor_1/2 — each filled name is one free voucher ticket). Children 12 & under are free (charging starts at 13) — stored and shown to gate staff, but not counted toward the total. Each adult name provided is stored and shown on a successful scan; the ticket title is the customer_name.

    Tickets are optional. A customer can buy ice, an ATV/UTV pass, or parking with no admission ticket, or buy tickets for other people. A record + QR is still created as long as there's something to redeem or verify at the gate (a ticket, ice, or an add-on). Only a truly empty order is rejected.

    Fields

    From 049f433930de3fa74fe1eecd57ce8e2043bd0a02 Mon Sep 17 00:00:00 2001 From: Hank Date: Mon, 20 Jul 2026 07:40:05 +0000 Subject: [PATCH 15/22] Fix ice bag count + default ice check-in to 1 bag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The form sends payment_ice as a descriptive label, e.g. "One Ice ticket good for one bag per day (3 total bags)". The old parser pulled the first number ("3") and treated it as 3 tickets, then multiplied by 3 bags/ticket → 9 bags for one ice ticket (18 for two). New iceBagsFromPayment reads the "(N total bags)" the label states directly, with worded-count and numeric dollar/count fallbacks for forward compatibility. 1 ice → 3 bags, 2 → 6. 5 new tests. Scanner: Ice mode now defaults the check-in count to 1 (a bag at a time) instead of all remaining bags; staff can bump it up. Co-Authored-By: Claude Opus 4.8 (1M context) --- app/app/index.tsx | 5 +++-- backend/src/fluentforms.ts | 28 ++++++++++++++++++++++++++++ backend/src/routes/webhook.ts | 13 +++++++------ backend/src/test/fluentforms.test.ts | 27 ++++++++++++++++++++++++++- 4 files changed, 64 insertions(+), 9 deletions(-) diff --git a/app/app/index.tsx b/app/app/index.tsx index d3211da..b7a0b2e 100644 --- a/app/app/index.tsx +++ b/app/app/index.tsx @@ -109,8 +109,9 @@ export default function ScannerScreen() { feedbackSuccess(); const remaining = mode === "ice" ? res.ticket.ice.remaining : res.ticket.remaining; setTicket(res.ticket); - // Ice: default to grabbing all remaining bags at once. Tickets: default 1. - setCount(mode === "ice" ? Math.max(1, remaining) : Math.min(1, remaining)); + // Default to 1 (people usually grab ice a bag at a time); staff can bump + // the count up. Clamp to what's left so a 0-remaining ticket stays at 0. + setCount(Math.min(1, remaining)); setPhase("confirm"); } catch (e: any) { if (e?.name === "AuthError") return router.replace("/login"); diff --git a/backend/src/fluentforms.ts b/backend/src/fluentforms.ts index de628a7..60f9e4c 100644 --- a/backend/src/fluentforms.ts +++ b/backend/src/fluentforms.ts @@ -56,6 +56,34 @@ export function addressLine(v: any): string | undefined { return undefined; } +const NUMBER_WORDS: Record = { one: 1, two: 2, three: 3, four: 4, five: 5, six: 6 }; + +/** + * Total bags of ice from the `payment_ice` field. The form sends a descriptive + * option label, e.g. "One Ice ticket good for one bag per day (3 total bags)", + * so the reliable signal is the "(N total bags)" the label states. Falls back to + * a worded ticket count ("Two Ice tickets" → 2 × bagsPerTicket), then to a + * numeric dollar-total/ticket-count for forward compatibility. + */ +export function iceBagsFromPayment( + value: unknown, + opts: { bagsPerTicket: number; ticketPrice: number }, +): number { + const { bagsPerTicket, ticketPrice } = opts; + const s = typeof value === "string" ? value : ""; + // Preferred: the label states the total bags directly. + const bagsMatch = s.match(/(\d+)\s*total\s*bags/i); + if (bagsMatch) return Math.max(0, parseInt(bagsMatch[1], 10)); + // Worded ticket count: "One Ice ticket", "Two Ice tickets". + const wordMatch = s.match(/\b(one|two|three|four|five|six)\b\s+ice/i); + if (wordMatch) return NUMBER_WORDS[wordMatch[1].toLowerCase()] * bagsPerTicket; + // Numeric fallback: a dollar total (>= price) → tickets; else a small count. + const n = qty(value); + if (n <= 0) return 0; + const tickets = n >= ticketPrice ? Math.round(n / ticketPrice) : Math.round(n); + return Math.max(0, tickets) * bagsPerTicket; +} + /** Donor status from the hidden lookup fields + the "are you a donor?" radio. */ export function readDonor(body: Record): { isDonor: boolean; donorTier: string } { const donorTier = String(body.donor_tier ?? "").trim(); diff --git a/backend/src/routes/webhook.ts b/backend/src/routes/webhook.ts index 7f5595d..250c14f 100644 --- a/backend/src/routes/webhook.ts +++ b/backend/src/routes/webhook.ts @@ -3,7 +3,7 @@ import type { FastifyInstance } from "fastify"; import { toBool } from "../fields.js"; import { createTicket } from "../ticketService.js"; import { renderQrPng } from "../services/qrcode.js"; -import { safeEqual, nameGroup, qty, selected, addressLine } from "../fluentforms.js"; +import { safeEqual, nameGroup, qty, selected, addressLine, iceBagsFromPayment } from "../fluentforms.js"; // Regular adult attendee name groups (Adult Ticket #1–#10), in order. const REGULAR_NAME_BASES = [ @@ -73,11 +73,12 @@ export async function webhookRoutes(app: FastifyInstance): Promise { const carParking = selected(body.payment_parking_reg) || selected(body.payment_parking_donor); const rvParking = selected(body.payment_rv_reg) || selected(body.payment_rv_donor); const utv = selected(body.payment_utv_reg) || selected(body.payment_utv_donor); - // Ice: payment_ice is either a ticket count (1-4) or a dollar total - // ($20-$80). One ice ticket = ICE_BAGS_PER_TICKET bags. - const iceRaw = qty(body.payment_ice); - const iceTickets = iceRaw >= app.ctx.config.ICE_TICKET_PRICE ? Math.round(iceRaw / app.ctx.config.ICE_TICKET_PRICE) : Math.round(iceRaw); - const iceBags = Math.max(0, iceTickets) * app.ctx.config.ICE_BAGS_PER_TICKET; + // Ice: payment_ice is a descriptive option label whose "(N total bags)" + // states the bags. One ice ticket = ICE_BAGS_PER_TICKET bags. + const iceBags = iceBagsFromPayment(body.payment_ice, { + bagsPerTicket: app.ctx.config.ICE_BAGS_PER_TICKET, + ticketPrice: app.ctx.config.ICE_TICKET_PRICE, + }); const iceAccess = iceBags > 0 || selected(body.input_radio_7); // Tickets are optional: a customer can buy ice/UTV/parking with no admission diff --git a/backend/src/test/fluentforms.test.ts b/backend/src/test/fluentforms.test.ts index 083f3b4..9023e24 100644 --- a/backend/src/test/fluentforms.test.ts +++ b/backend/src/test/fluentforms.test.ts @@ -1,5 +1,7 @@ import { describe, it, expect } from "vitest"; -import { nameGroup, qty, selected, addressLine, readDonor } from "../fluentforms.js"; +import { nameGroup, qty, selected, addressLine, readDonor, iceBagsFromPayment } from "../fluentforms.js"; + +const ICE = { bagsPerTicket: 3, ticketPrice: 20 }; // Food vendors are the only vendor tickets; two pass-holder name slots. const FOOD_SLOTS = ["names", "names_1"]; @@ -44,6 +46,29 @@ describe("food vendor pass counting", () => { }); }); +describe("iceBagsFromPayment", () => { + it("reads '(N total bags)' from the real form label", () => { + expect(iceBagsFromPayment("One Ice ticket good for one bag per day (3 total bags)", ICE)).toBe(3); + expect(iceBagsFromPayment("Two Ice tickets good for one bag per day (6 total bags)", ICE)).toBe(6); + }); + it("falls back to a worded ice-ticket count", () => { + expect(iceBagsFromPayment("Two Ice tickets", ICE)).toBe(6); // 2 × 3 + expect(iceBagsFromPayment("Four Ice tickets", ICE)).toBe(12); + }); + it("falls back to a dollar total at the ticket price", () => { + expect(iceBagsFromPayment("$40.00", ICE)).toBe(6); // 2 tickets × 3 + expect(iceBagsFromPayment(20, ICE)).toBe(3); // 1 ticket × 3 + }); + it("treats a small plain count as ticket count", () => { + expect(iceBagsFromPayment(2, ICE)).toBe(6); // 2 tickets × 3 + }); + it("is 0 for blank / no ice", () => { + expect(iceBagsFromPayment("", ICE)).toBe(0); + expect(iceBagsFromPayment(undefined, ICE)).toBe(0); + expect(iceBagsFromPayment(0, ICE)).toBe(0); + }); +}); + describe("readDonor", () => { it("treats donor_tier=member as a donor", () => { expect(readDonor({ donor_tier: "member" })).toEqual({ isDonor: true, donorTier: "member" }); From 63e00fae618851640bdbfd35116e02b484879dd8 Mon Sep 17 00:00:00 2001 From: Hank Date: Mon, 20 Jul 2026 18:48:10 +0000 Subject: [PATCH 16/22] Scanner: large Adults / Kids party panel on scan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gate-enforcement aid against adults signing up under a free/cheaper kid bracket. When a ticket is scanned, a prominent amber-bordered panel shows big "# ADULTS # KIDS" counts (Adults = the 18+ bracket; Kids = youth 13-16 + all under-13), plus a per-bracket detail line (e.g. "1× 13-16 · 2× 5-9") so staff can eyeball the claimed ages against the actual party. Shown on the confirm card (before check-in) and the success overlay; hidden in Ice mode. Co-Authored-By: Claude Opus 4.8 (1M context) --- app/app/index.tsx | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/app/app/index.tsx b/app/app/index.tsx index b7a0b2e..3766c6c 100644 --- a/app/app/index.tsx +++ b/app/app/index.tsx @@ -253,6 +253,7 @@ export default function ScannerScreen() { {ticket.redeemed} of {ticket.total} redeemed · {ticket.remaining} remaining + @@ -394,6 +395,37 @@ function AdultNames({ names }: { names: string[] }) { ); } +/** + * Big Adults / Kids breakdown so gate staff can eyeball the party against the + * ticket — a deterrent for adults signing up under a (free/cheaper) kid bracket. + * Adults = the 18+ bracket; Kids = everyone else (youth 13-16 + all under-13). + */ +function PartyPanel({ ticket }: { ticket: TicketView }) { + const adults = ticket.ages.find((a) => a.bracket === "Adults")?.count ?? 0; + const kidBrackets = ticket.ages.filter((a) => a.bracket !== "Adults"); + const kids = kidBrackets.reduce((s, a) => s + a.count, 0); + return ( + + + + {adults} + {adults === 1 ? "ADULT" : "ADULTS"} + + + + {kids} + {kids === 1 ? "KID" : "KIDS"} + + + {kidBrackets.length > 0 && ( + + {kidBrackets.map((a) => `${a.count}× ${a.bracket.replace(/^(Kids|Youth)\s*/, "")}`).join(" · ")} + + )} + + ); +} + function ConfirmCard({ ticket, isIce, @@ -422,6 +454,7 @@ function ConfirmCard({ {ticket.name} {ticket.code} + {!isIce && } {remaining} of {total} {unit} remaining @@ -535,6 +568,23 @@ const styles = StyleSheet.create({ typeBadgeText: { color: "#fff", fontSize: 20, fontWeight: "900", letterSpacing: 1 }, namesBox: { marginTop: 12, alignItems: "center", gap: 3 }, nameLine: { color: "#fff", fontSize: 18, fontWeight: "600", textAlign: "center" }, + party: { + alignSelf: "stretch", + backgroundColor: "#1d2a1f", + borderWidth: 2, + borderColor: theme.warn, + borderRadius: 16, + paddingVertical: 18, + paddingHorizontal: 12, + marginTop: 16, + marginBottom: 2, + }, + partyRow: { flexDirection: "row", alignItems: "center", justifyContent: "center" }, + partyCell: { flex: 1, alignItems: "center" }, + partyNum: { color: theme.text, fontSize: 60, fontWeight: "900", lineHeight: 64 }, + partyLbl: { color: theme.warn, fontSize: 15, fontWeight: "800", letterSpacing: 2, marginTop: 2 }, + partyDivider: { width: 2, alignSelf: "stretch", backgroundColor: theme.cardBorder, marginVertical: 6 }, + partyDetail: { color: theme.textDim, fontSize: 14, textAlign: "center", marginTop: 12, fontWeight: "600" }, tags: { flexDirection: "row", flexWrap: "wrap", justifyContent: "center", gap: 8, marginTop: 14 }, tag: { color: "#fff", backgroundColor: "rgba(255,255,255,0.18)", paddingHorizontal: 10, paddingVertical: 5, borderRadius: 999, fontSize: 13, overflow: "hidden" }, From 62231e9b1070896dad05b02a634afaf6c6236407 Mon Sep 17 00:00:00 2001 From: Hank Date: Tue, 21 Jul 2026 00:34:32 +0000 Subject: [PATCH 17/22] Release v0.2.0 (versionCode 2) Webhook: Tickets 2026 form (customer_name title, voucher-name ticket counting, ticketless ice/UTV orders, donor adult names); ice bag count fix; voucher decrement; vendor webhooks; free kids through 12; multi- origin lookup CORS; scanner Adults/Kids party panel + ice default 1. First versionCode bump (was stuck at 1), so this installs over v0.1.0. Co-Authored-By: Claude Opus 4.8 (1M context) --- app/app.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/app.json b/app/app.json index 143c506..ecfabbc 100644 --- a/app/app.json +++ b/app/app.json @@ -2,7 +2,7 @@ "expo": { "name": "Camp Scan", "slug": "camptickets", - "version": "0.1.0", + "version": "0.2.0", "orientation": "portrait", "scheme": "campscan", "userInterfaceStyle": "automatic", @@ -10,7 +10,7 @@ "icon": "./assets/icon.png", "android": { "package": "top.mowden.campscan", - "versionCode": 1, + "versionCode": 2, "adaptiveIcon": { "foregroundImage": "./assets/adaptive-icon.png", "backgroundColor": "#0f1a12" From 60f090829916a04b3c7ff392864f8117b784d3af Mon Sep 17 00:00:00 2001 From: Hank Date: Wed, 22 Jul 2026 03:34:14 +0000 Subject: [PATCH 18/22] Scanner: compact 3-cell Adults / Youth / Kids party panel Split the party panel into Adults (18+) / Youth (13-16) / Kids (0-12) so the paid tickets (adults + youth) are both visible, and shrank it (36px numbers, tighter padding, single-line kid detail) so the confirm card no longer scrolls on a phone. Co-Authored-By: Claude Opus 4.8 (1M context) --- app/app/index.tsx | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/app/app/index.tsx b/app/app/index.tsx index 3766c6c..e624c36 100644 --- a/app/app/index.tsx +++ b/app/app/index.tsx @@ -396,30 +396,38 @@ function AdultNames({ names }: { names: string[] }) { } /** - * Big Adults / Kids breakdown so gate staff can eyeball the party against the - * ticket — a deterrent for adults signing up under a (free/cheaper) kid bracket. - * Adults = the 18+ bracket; Kids = everyone else (youth 13-16 + all under-13). + * Big Adults / Youth / Kids breakdown so gate staff can eyeball the party + * against the ticket — a deterrent for adults signing up under a (free/cheaper) + * younger bracket. Adults (18+) and Youth (13-16) are the paid tickets; Kids + * (0-12) are free. A detail line breaks the kids into their age bands. */ function PartyPanel({ ticket }: { ticket: TicketView }) { - const adults = ticket.ages.find((a) => a.bracket === "Adults")?.count ?? 0; - const kidBrackets = ticket.ages.filter((a) => a.bracket !== "Adults"); + const get = (b: string) => ticket.ages.find((a) => a.bracket === b)?.count ?? 0; + const adults = get("Adults"); + const youth = get("Youth 13-16"); + const kidBrackets = ticket.ages.filter((a) => a.bracket.startsWith("Kids")); const kids = kidBrackets.reduce((s, a) => s + a.count, 0); return ( {adults} - {adults === 1 ? "ADULT" : "ADULTS"} + ADULTS{"\n"}18+ + + + + {youth} + YOUTH{"\n"}13-16 {kids} - {kids === 1 ? "KID" : "KIDS"} + KIDS{"\n"}0-12 {kidBrackets.length > 0 && ( - {kidBrackets.map((a) => `${a.count}× ${a.bracket.replace(/^(Kids|Youth)\s*/, "")}`).join(" · ")} + kids: {kidBrackets.map((a) => `${a.count}× ${a.bracket.replace(/^Kids\s*/, "")}`).join(" · ")} )} @@ -573,18 +581,18 @@ const styles = StyleSheet.create({ backgroundColor: "#1d2a1f", borderWidth: 2, borderColor: theme.warn, - borderRadius: 16, - paddingVertical: 18, - paddingHorizontal: 12, - marginTop: 16, + borderRadius: 14, + paddingVertical: 10, + paddingHorizontal: 10, + marginTop: 10, marginBottom: 2, }, partyRow: { flexDirection: "row", alignItems: "center", justifyContent: "center" }, partyCell: { flex: 1, alignItems: "center" }, - partyNum: { color: theme.text, fontSize: 60, fontWeight: "900", lineHeight: 64 }, - partyLbl: { color: theme.warn, fontSize: 15, fontWeight: "800", letterSpacing: 2, marginTop: 2 }, - partyDivider: { width: 2, alignSelf: "stretch", backgroundColor: theme.cardBorder, marginVertical: 6 }, - partyDetail: { color: theme.textDim, fontSize: 14, textAlign: "center", marginTop: 12, fontWeight: "600" }, + partyNum: { color: theme.text, fontSize: 36, fontWeight: "900", lineHeight: 40 }, + partyLbl: { color: theme.warn, fontSize: 11, fontWeight: "800", letterSpacing: 0.5, marginTop: 1, textAlign: "center", lineHeight: 13 }, + partyDivider: { width: 1.5, height: 42, backgroundColor: theme.cardBorder }, + partyDetail: { color: theme.textDim, fontSize: 12, textAlign: "center", marginTop: 8, fontWeight: "600" }, tags: { flexDirection: "row", flexWrap: "wrap", justifyContent: "center", gap: 8, marginTop: 14 }, tag: { color: "#fff", backgroundColor: "rgba(255,255,255,0.18)", paddingHorizontal: 10, paddingVertical: 5, borderRadius: 999, fontSize: 13, overflow: "hidden" }, From 3a3119e3240d0b33173b3e9ef8a58c802f973628 Mon Sep 17 00:00:00 2001 From: Hank Date: Thu, 23 Jul 2026 01:29:10 +0000 Subject: [PATCH 19/22] Admin hub in /crush33: sidebar, donor lookup, danger-zone actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rebuilt the password-gated /crush33 (in-app /comp) screen into an admin hub with a left sidebar and three sections: - Comp tickets — the existing entry-only comp creator. - Donor lookup — admin-only free-text search across the donor master list + online/offline transaction tables by name / email / phone / address / bear name (columns discovered per table, deduped by email). - Actions (danger zone) — heavy warnings, red buttons, and an "are you sure" modal that spells out exactly what will happen: • Wipe slate — delete ALL ticket + audit records in the active event table (donor data untouched, irreversible). • Switch event table — repoint the app at a different NocoDB tickets/audit table to start a new event while keeping the old one intact. Backend: - New /api/admin/{status,wipe,switch-table,donor-search}, all gated by PORTAL_PASSWORD (POST-only so it never lands in a URL/log). - NocoDBClient + AuditLogger: runtime-switchable tableId, count(), deleteAll(), probeTable() (reachable + Id-PK check before switching). - DonorService.search() with adaptive column discovery. - Table switch persists across redeploys via a small state file on a new /data volume (Dockerfile creates it owned by node so it's writable); applied at startup in buildContext. Also shipped equivalent CLI scripts: scripts/wipe-slate.sh and scripts/switch-event.sh. Drawer: "Comp tickets" -> "Admin (crush33)". Co-Authored-By: Claude Opus 4.8 (1M context) --- Dockerfile | 7 +- app/app/comp.tsx | 630 ++++++++++++++++++++++++--------- app/components/SideMenu.tsx | 4 +- app/lib/api.ts | 50 +++ backend/src/config.ts | 4 + backend/src/context.ts | 16 +- backend/src/routes/admin.ts | 122 +++++++ backend/src/server.ts | 2 + backend/src/services/audit.ts | 48 ++- backend/src/services/donors.ts | 107 ++++++ backend/src/services/nocodb.ts | 55 ++- backend/src/services/state.ts | 32 ++ docker-compose.yml | 7 + scripts/switch-event.sh | 73 ++++ scripts/wipe-slate.sh | 57 +++ 15 files changed, 1042 insertions(+), 172 deletions(-) create mode 100644 backend/src/routes/admin.ts create mode 100644 backend/src/services/state.ts create mode 100755 scripts/switch-event.sh create mode 100755 scripts/wipe-slate.sh diff --git a/Dockerfile b/Dockerfile index 845477a..e5ce281 100644 --- a/Dockerfile +++ b/Dockerfile @@ -32,8 +32,11 @@ ENV WEB_DIR=/srv/web ENV PORT=8080 ENV HOST=0.0.0.0 -# Run as the non-root node user shipped in the base image. -RUN chown -R node:node /srv +# Run as the non-root node user shipped in the base image. /data is a mount +# point for the runtime state volume — create it owned by node so a fresh named +# volume inherits writable ownership. +RUN chown -R node:node /srv && mkdir -p /data && chown node:node /data +ENV STATE_DIR=/data USER node EXPOSE 8080 diff --git a/app/app/comp.tsx b/app/app/comp.tsx index 364aac0..648af1e 100644 --- a/app/app/comp.tsx +++ b/app/app/comp.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useState, useCallback, useEffect } from "react"; import { StyleSheet, View, @@ -9,10 +9,21 @@ import { Image, KeyboardAvoidingView, Platform, + ActivityIndicator, } from "react-native"; -import { router } from "expo-router"; import { SafeAreaView } from "react-native-safe-area-context"; -import { portalVerify, portalCreate, AuthError, type PortalTicket } from "../lib/api"; +import { + portalVerify, + portalCreate, + adminStatus, + adminWipe, + adminSwitchTable, + adminDonorSearch, + AuthError, + type PortalTicket, + type AdminStatus, + type DonorSearchResult, +} from "../lib/api"; import { useAuth } from "../lib/auth"; import { useMenu } from "../lib/menu"; import { theme } from "../lib/theme"; @@ -26,18 +37,26 @@ const TYPE_ICON: Record = { Speaker: "🎤", }; -export default function CompScreen() { +type Section = "comp" | "donors" | "actions"; +const NAV: { key: Section; icon: string; label: string }[] = [ + { key: "comp", icon: "🎟️", label: "Comp\ntickets" }, + { key: "donors", icon: "🔎", label: "Donor\nlookup" }, + { key: "actions", icon: "⚠️", label: "Actions" }, +]; + +export default function AdminHub() { const { operator } = useAuth(); const { open: openMenu } = useMenu(); const [password, setPassword] = useState(""); const [unlocked, setUnlocked] = useState(false); const [busy, setBusy] = useState(false); const [error, setError] = useState(""); + const [section, setSection] = useState
    ("comp"); - const [type, setType] = useState("Guest"); - const [name, setName] = useState(""); - const [email, setEmail] = useState(""); - const [result, setResult] = useState(null); + const relock = useCallback(() => { + setUnlocked(false); + setError("Password changed — unlock again."); + }, []); async function unlock() { if (!password || busy) return; @@ -47,28 +66,7 @@ export default function CompScreen() { await portalVerify(password); setUnlocked(true); } catch (e: any) { - setError(e instanceof AuthError ? "Wrong password" : (e?.message ?? "Failed")); - } finally { - setBusy(false); - } - } - - async function create() { - if (!name.trim() || !email.trim() || busy) return; - setBusy(true); - setError(""); - try { - const r = await portalCreate({ password, name: name.trim(), email: email.trim(), type, createdBy: operator }); - setResult(r); - setName(""); - setEmail(""); - } catch (e: any) { - if (e instanceof AuthError) { - setUnlocked(false); // password rotated — re-gate - setError("Password changed — unlock again."); - } else { - setError(e?.message ?? "Failed to create ticket"); - } + setError(e instanceof AuthError ? "Wrong password" : e?.message ?? "Failed"); } finally { setBusy(false); } @@ -80,160 +78,468 @@ export default function CompScreen() { - Comp Tickets + Admin · crush33 - - - {!unlocked ? ( - - Entry-only tickets for workers & guests. Enter the shared portal password. - Portal password - - {!!error && {error}} - - {busy ? "Checking…" : "Unlock"} - - - ) : ( - - Ticket type - - {TYPES.map((t) => ( - setType(t)} - > - - {(TYPE_ICON[t] ?? "🎫") + " " + t} - - - ))} - + {!unlocked ? ( + + + Admin-only area. Enter the shared portal password to unlock. + Portal password + + {!!error && {error}} + + {busy ? "Checking…" : "Unlock"} + + + + ) : ( + + + {NAV.map((n) => { + const active = section === n.key; + return ( + setSection(n.key)}> + {n.icon} + {n.label} + + ); + })} + - Full name - - - Email - - - {!!error && {error}} - - {busy ? "Creating…" : `Create ${type} ticket`} - - - {result && ( - - - {result.code} - - {result.type} · {result.name} - - - {result.emailSent ? "✓ Emailed the ticket" : "Email not sent — screenshot this QR"} - - - )} - - )} - - + + + {section === "comp" && } + {section === "donors" && } + {section === "actions" && } + + + + )} ); } +/* ---------------- Comp tickets ---------------- */ + +function CompSection({ password, operator, onRelock }: { password: string; operator: string | null; onRelock: () => void }) { + const [type, setType] = useState("Guest"); + const [name, setName] = useState(""); + const [email, setEmail] = useState(""); + const [busy, setBusy] = useState(false); + const [error, setError] = useState(""); + const [result, setResult] = useState(null); + + async function create() { + if (!name.trim() || !email.trim() || busy) return; + setBusy(true); + setError(""); + try { + const r = await portalCreate({ password, name: name.trim(), email: email.trim(), type, createdBy: operator ?? "" }); + setResult(r); + setName(""); + setEmail(""); + } catch (e: any) { + if (e instanceof AuthError) onRelock(); + else setError(e?.message ?? "Failed to create ticket"); + } finally { + setBusy(false); + } + } + + return ( + + Comp tickets + Entry-only tickets for guests & staff. + + Ticket type + + {TYPES.map((t) => ( + setType(t)}> + {(TYPE_ICON[t] ?? "🎫") + " " + t} + + ))} + + + Full name + + Email + + + {!!error && {error}} + + {busy ? "Creating…" : `Create ${type} ticket`} + + + {result && ( + + + {result.code} + {result.type} · {result.name} + {result.emailSent ? "✓ Emailed the ticket" : "Email not sent — screenshot this QR"} + + )} + + ); +} + +/* ---------------- Donor lookup ---------------- */ + +function DonorSection({ password, onRelock }: { password: string; onRelock: () => void }) { + const [query, setQuery] = useState(""); + const [busy, setBusy] = useState(false); + const [error, setError] = useState(""); + const [results, setResults] = useState(null); + + async function run() { + const q = query.trim(); + if (q.length < 2 || busy) return; + setBusy(true); + setError(""); + try { + const r = await adminDonorSearch(password, q); + setResults(r.results); + } catch (e: any) { + if (e instanceof AuthError) onRelock(); + else setError(e?.message ?? "Search failed"); + } finally { + setBusy(false); + } + } + + return ( + + Donor lookup + 🔒 Admin only · private donor info. Search by name, email, phone, address, bear name… + + + + + {busy ? "…" : "Search"} + + + + {!!error && {error}} + {results !== null && !busy && results.length === 0 && No donors match “{query.trim()}”.} + + {results?.map((d, i) => ( + + + {d.name || d.email || "(unnamed)"} + {d.lifetime != null && {money(d.lifetime)}} + + {!!d.bearName && 🐻 {d.bearName}} + {!!d.email && ✉️ {d.email}} + {!!d.altEmail && ✉️ {d.altEmail} (alt)} + {!!d.phone && 📞 {d.phone}} + {!!d.address && 🏠 {d.address}} + + {d.source === "master" ? "directory" : "transactions"} + {d.tags.map((t) => ( + {t} + ))} + + + ))} + + ); +} + +/* ---------------- Actions (danger zone) ---------------- */ + +function ActionsSection({ password, onRelock }: { password: string; onRelock: () => void }) { + const [status, setStatus] = useState(null); + const [loading, setLoading] = useState(false); + const [msg, setMsg] = useState(""); + const [confirm, setConfirm] = useState(null); + const [busy, setBusy] = useState(false); + const [newTickets, setNewTickets] = useState(""); + const [newAudit, setNewAudit] = useState(""); + + const refresh = useCallback(async () => { + setLoading(true); + try { + setStatus(await adminStatus(password)); + } catch (e: any) { + if (e instanceof AuthError) onRelock(); + } finally { + setLoading(false); + } + }, [password, onRelock]); + + // Load status the first time this section renders. + useEffect(() => { + refresh(); + }, [refresh]); + + async function doWipe() { + setBusy(true); + setMsg(""); + try { + const r = await adminWipe(password); + setMsg(`✓ Wiped ${r.ticketsDeleted} tickets and ${r.auditDeleted} audit rows.`); + setConfirm(null); + refresh(); + } catch (e: any) { + if (e instanceof AuthError) onRelock(); + else setMsg(e?.message ?? "Wipe failed"); + } finally { + setBusy(false); + } + } + + async function doSwitch() { + if (!newTickets.trim()) return; + setBusy(true); + setMsg(""); + try { + const r = await adminSwitchTable(password, newTickets.trim(), newAudit.trim() || undefined); + setMsg(`✓ Now using tickets table ${r.tickets.tableId}.`); + setConfirm(null); + setNewTickets(""); + setNewAudit(""); + refresh(); + } catch (e: any) { + if (e instanceof AuthError) onRelock(); + else setMsg(e?.message ?? "Switch failed"); + } finally { + setBusy(false); + } + } + + return ( + + Actions + Event-management tools. These change live data — read the warnings. + + {/* Current status */} + + + Active event table + + {loading ? "…" : "↻"} + + + {status ? ( + <> + tickets: {status.tickets.tableId} · {status.tickets.count} records + audit: {status.audit.tableId ?? "—"} · {status.audit.count} records + + ) : ( + {loading ? "loading…" : "—"} + )} + + + {!!msg && {msg}} + + {/* Wipe slate */} + + 🧹 Wipe the slate clean + + Permanently deletes every ticket and every check-in in the active event + table. Use this to reset before a run-through or a fresh event. + + • Does NOT affect donor data. + • Cannot be undone. + { setMsg(""); setConfirm("wipe"); }}> + Wipe slate… + + + + {/* Switch table */} + + 🔀 Switch event table + + Point the scanner at a different NocoDB table — e.g. to start a new event on + a fresh table while keeping the current one intact. + + • Create the new table first (duplicate the current one's structure in NocoDB — keep the Id column). + • The current event's data is NOT deleted, just no longer shown. + New tickets table ID + + New audit table ID (optional) + + { setMsg(""); setConfirm("switch"); }} disabled={!newTickets.trim()}> + Switch table… + + + + {confirm === "wipe" && ( + setConfirm(null)} + /> + )} + {confirm === "switch" && ( + setConfirm(null)} + /> + )} + + ); +} + +function ConfirmModal({ + title, + lines, + confirmLabel, + busy, + onConfirm, + onCancel, +}: { + title: string; + lines: string[]; + confirmLabel: string; + busy: boolean; + onConfirm: () => void; + onCancel: () => void; +}) { + return ( + + + ⚠️ + {title} + {lines.map((l, i) => ( + {l} + ))} + + {busy ? : {confirmLabel}} + + + Cancel + + + + ); +} + +function money(n: number): string { + return "$" + Math.round(n).toLocaleString(); +} + const styles = StyleSheet.create({ root: { flex: 1, backgroundColor: theme.bg }, - topbar: { - flexDirection: "row", - alignItems: "center", - justifyContent: "space-between", - paddingHorizontal: 16, - paddingVertical: 10, - }, + topbar: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingHorizontal: 16, paddingVertical: 10 }, brand: { color: theme.text, fontSize: 18, fontWeight: "700" }, hamburger: { color: theme.text, fontSize: 26, fontWeight: "700" }, - link: { color: theme.textDim, fontSize: 16, fontWeight: "600", width: 72 }, + + body: { flex: 1, flexDirection: "row" }, + sidebar: { width: 84, backgroundColor: theme.card, borderRightWidth: 1, borderRightColor: theme.cardBorder, paddingTop: 8 }, + navItem: { paddingVertical: 14, alignItems: "center", gap: 4, borderLeftWidth: 3, borderLeftColor: "transparent" }, + navItemOn: { backgroundColor: theme.bg, borderLeftColor: theme.primary }, + navIcon: { fontSize: 22 }, + navLabel: { color: theme.textDim, fontSize: 11, fontWeight: "700", textAlign: "center", lineHeight: 13 }, + navLabelOn: { color: theme.text }, + content: { flex: 1 }, + pad: { padding: 16, paddingBottom: 48 }, + + h1: { color: theme.text, fontSize: 22, fontWeight: "800", marginBottom: 2 }, + sub: { color: theme.textDim, fontSize: 13, lineHeight: 19, marginBottom: 8 }, lead: { color: theme.textDim, fontSize: 15, lineHeight: 21, marginBottom: 8 }, - label: { color: theme.textDim, fontSize: 13, marginTop: 16, marginBottom: 6 }, - input: { - backgroundColor: theme.card, - borderWidth: 1, - borderColor: theme.cardBorder, - borderRadius: 12, - paddingHorizontal: 14, - paddingVertical: 14, - color: theme.text, - fontSize: 16, - }, + label: { color: theme.textDim, fontSize: 13, marginTop: 14, marginBottom: 6 }, + input: { backgroundColor: theme.card, borderWidth: 1, borderColor: theme.cardBorder, borderRadius: 12, paddingHorizontal: 14, paddingVertical: 12, color: theme.text, fontSize: 16, marginBottom: 2 }, error: { color: theme.dangerBright, marginTop: 12, fontSize: 14, fontWeight: "600" }, - btn: { - backgroundColor: theme.successBright, - borderRadius: 13, - paddingVertical: 15, - alignItems: "center", - marginTop: 20, - }, + msg: { color: theme.successBright, marginTop: 10, fontSize: 14, fontWeight: "700" }, + bold: { fontWeight: "800", color: theme.text }, + + btn: { backgroundColor: theme.successBright, borderRadius: 13, paddingVertical: 15, alignItems: "center", marginTop: 18 }, btnOff: { opacity: 0.4 }, btnText: { color: "#06210f", fontSize: 18, fontWeight: "800" }, types: { flexDirection: "row", flexWrap: "wrap", gap: 8 }, - typePill: { - backgroundColor: theme.card, - borderWidth: 1, - borderColor: theme.cardBorder, - borderRadius: 999, - paddingHorizontal: 14, - paddingVertical: 9, - }, + typePill: { backgroundColor: theme.card, borderWidth: 1, borderColor: theme.cardBorder, borderRadius: 999, paddingHorizontal: 13, paddingVertical: 8 }, typePillOn: { backgroundColor: theme.primary, borderColor: theme.primary }, - typePillText: { color: theme.textDim, fontSize: 14, fontWeight: "700" }, + typePillText: { color: theme.textDim, fontSize: 13, fontWeight: "700" }, typePillTextOn: { color: "#fff" }, - result: { - marginTop: 22, - alignItems: "center", - backgroundColor: theme.card, - borderWidth: 1, - borderColor: theme.cardBorder, - borderRadius: 16, - padding: 20, - }, - qr: { width: 220, height: 220, backgroundColor: "#fff", borderRadius: 10 }, + result: { marginTop: 22, alignItems: "center", backgroundColor: theme.card, borderWidth: 1, borderColor: theme.cardBorder, borderRadius: 16, padding: 20 }, + qr: { width: 200, height: 200, backgroundColor: "#fff", borderRadius: 10 }, rcode: { color: theme.successBright, fontSize: 22, fontWeight: "800", letterSpacing: 2, marginTop: 12 }, rwho: { color: theme.text, fontSize: 16, marginTop: 4 }, rmail: { color: theme.textDim, fontSize: 13, marginTop: 8 }, + + searchRow: { flexDirection: "row", gap: 8, alignItems: "center", marginTop: 8 }, + searchBtn: { backgroundColor: theme.primary, borderRadius: 12, paddingHorizontal: 16, paddingVertical: 13 }, + searchBtnText: { color: "#fff", fontWeight: "800", fontSize: 15 }, + donorCard: { backgroundColor: theme.card, borderWidth: 1, borderColor: theme.cardBorder, borderRadius: 12, padding: 14, marginTop: 12 }, + donorHead: { flexDirection: "row", justifyContent: "space-between", alignItems: "center" }, + donorName: { color: theme.text, fontSize: 17, fontWeight: "800", flex: 1 }, + donorAmt: { color: theme.successBright, fontSize: 16, fontWeight: "800", marginLeft: 8 }, + donorLine: { color: theme.textDim, fontSize: 14, marginTop: 3 }, + donorTags: { flexDirection: "row", flexWrap: "wrap", gap: 6, marginTop: 8, alignItems: "center" }, + donorSource: { color: theme.textDim, fontSize: 11, fontWeight: "700", textTransform: "uppercase", backgroundColor: theme.bg, borderWidth: 1, borderColor: theme.cardBorder, borderRadius: 6, paddingHorizontal: 6, paddingVertical: 2 }, + donorTag: { color: theme.text, fontSize: 12, backgroundColor: theme.primaryDark, borderRadius: 6, paddingHorizontal: 7, paddingVertical: 2 }, + + statusBox: { backgroundColor: theme.card, borderWidth: 1, borderColor: theme.cardBorder, borderRadius: 12, padding: 14, marginTop: 4 }, + statusRow: { flexDirection: "row", justifyContent: "space-between", alignItems: "center" }, + statusLabel: { color: theme.textDim, fontSize: 12, fontWeight: "700", textTransform: "uppercase", letterSpacing: 0.5 }, + refresh: { color: theme.text, fontSize: 20 }, + statusVal: { color: theme.text, fontSize: 14, marginTop: 6, fontFamily: Platform.OS === "ios" ? "Menlo" : "monospace" }, + + dangerCard: { backgroundColor: "#241717", borderWidth: 1, borderColor: theme.danger, borderRadius: 14, padding: 16, marginTop: 18 }, + dangerTitle: { color: "#ff9a9a", fontSize: 17, fontWeight: "800", marginBottom: 6 }, + dangerBody: { color: "#e9cfcf", fontSize: 14, lineHeight: 20 }, + dangerBullet: { color: "#d9b8b8", fontSize: 13, lineHeight: 19, marginTop: 4 }, + redBtn: { backgroundColor: theme.dangerBright, borderRadius: 12, paddingVertical: 14, alignItems: "center", marginTop: 16 }, + redBtnText: { color: "#fff", fontSize: 16, fontWeight: "800" }, + + modalScrim: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0, backgroundColor: "rgba(0,0,0,0.72)", alignItems: "center", justifyContent: "center", padding: 24 }, + modalCard: { backgroundColor: "#1a1010", borderWidth: 2, borderColor: theme.dangerBright, borderRadius: 18, padding: 22, width: "100%", maxWidth: 380 }, + modalWarn: { fontSize: 40, textAlign: "center" }, + modalTitle: { color: "#fff", fontSize: 20, fontWeight: "900", textAlign: "center", marginTop: 4, marginBottom: 12 }, + modalLine: { color: "#f0d9d9", fontSize: 14, lineHeight: 20 }, + cancelBtn: { paddingVertical: 14, alignItems: "center", marginTop: 6 }, + cancelText: { color: theme.textDim, fontSize: 16, fontWeight: "700" }, }); diff --git a/app/components/SideMenu.tsx b/app/components/SideMenu.tsx index 522b2c3..890027b 100644 --- a/app/components/SideMenu.tsx +++ b/app/components/SideMenu.tsx @@ -7,8 +7,8 @@ import { theme } from "../lib/theme"; const ITEMS: { label: string; icon: string; route: string; seg: string }[] = [ { label: "Scanner", icon: "📷", route: "/", seg: "" }, { label: "Event report", icon: "📊", route: "/stats", seg: "stats" }, - { label: "Comp tickets", icon: "🎟️", route: "/comp", seg: "comp" }, - { label: "Admin lookup", icon: "🔎", route: "/admin", seg: "admin" }, + { label: "Admin (crush33)", icon: "🔐", route: "/comp", seg: "comp" }, + { label: "Banquet lookup", icon: "🍽️", route: "/admin", seg: "admin" }, ]; export default function SideMenu({ visible, onClose }: { visible: boolean; onClose: () => void }) { diff --git a/app/lib/api.ts b/app/lib/api.ts index 9f9d4f1..d574790 100644 --- a/app/lib/api.ts +++ b/app/lib/api.ts @@ -252,6 +252,56 @@ export async function portalCreate(input: { return body; } +// ---- Admin actions (all gated by the portal password) ---- + +async function adminPost(path: string, password: string, extra: Record = {}): Promise { + const res = await fetch(`${API_BASE}${path}`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ password, ...extra }), + }); + if (res.status === 401) throw new AuthError("Wrong password"); + const body = await res.json().catch(() => ({})); + if (!res.ok) throw new ApiError(body?.detail ?? body?.error ?? `Request failed (${res.status})`); + return body as T; +} + +export interface AdminStatus { + tickets: { tableId: string; count: number }; + audit: { tableId: string | null; count: number; enabled: boolean }; + defaults: { ticketsTableId: string; auditTableId: string | null }; +} +export function adminStatus(password: string): Promise { + return adminPost("/api/admin/status", password); +} + +export function adminWipe(password: string): Promise<{ ok: boolean; ticketsDeleted: number; auditDeleted: number }> { + return adminPost("/api/admin/wipe", password); +} + +export function adminSwitchTable( + password: string, + ticketsTableId: string, + auditTableId?: string, +): Promise<{ ok: boolean; tickets: { tableId: string }; audit: { tableId: string | null } }> { + return adminPost("/api/admin/switch-table", password, { ticketsTableId, auditTableId }); +} + +export interface DonorSearchResult { + name: string; + bearName: string; + email: string; + altEmail: string; + phone: string; + address: string; + lifetime: number | null; + tags: string[]; + source: "master" | "transactions"; +} +export function adminDonorSearch(password: string, query: string): Promise<{ results: DonorSearchResult[]; query: string }> { + return adminPost("/api/admin/donor-search", password, { query }); +} + export function getAudit(opts: { code?: string; limit?: number } = {}): Promise<{ enabled: boolean; entries: AuditEntry[]; diff --git a/backend/src/config.ts b/backend/src/config.ts index 88954cf..944dd0f 100644 --- a/backend/src/config.ts +++ b/backend/src/config.ts @@ -10,6 +10,10 @@ const schema = z.object({ // Optional "2026 Ticket Audit Logs" table. If unset, audit logging is skipped. NOCODB_AUDIT_TABLE_ID: z.string().optional(), + // Writable dir (mounted volume) for small runtime state — e.g. the active + // event table override set from the admin area, so it survives redeploys. + STATE_DIR: z.string().default("/data"), + // Donor tables for Banquet mode. If the master-list id is unset, banquet is // disabled. Online/offline are used as a fallback when a donor is not in the // master list. diff --git a/backend/src/context.ts b/backend/src/context.ts index fcf2c43..9bf2e2c 100644 --- a/backend/src/context.ts +++ b/backend/src/context.ts @@ -4,6 +4,7 @@ import { Mailer } from "./services/mailer.js"; import { RedeemQueue } from "./services/redeemQueue.js"; import { AuditLogger } from "./services/audit.js"; import { DonorService } from "./services/donors.js"; +import { loadActiveTables } from "./services/state.js"; /** Shared services wired once at startup and hung off the Fastify instance. */ export interface AppContext { @@ -16,12 +17,23 @@ export interface AppContext { } export function buildContext(config: Config): AppContext { + const nocodb = new NocoDBClient(config); + const audit = new AuditLogger(config); + + // Apply a persisted "active event table" override (set from the admin area), + // so switching the event survives redeploys without editing .env. + const override = loadActiveTables(config.STATE_DIR); + if (override) { + nocodb.setTableId(override.ticketsTableId); + audit.setTableId(override.auditTableId ?? null); + } + return { config, - nocodb: new NocoDBClient(config), + nocodb, mailer: new Mailer(config), queue: new RedeemQueue(), - audit: new AuditLogger(config), + audit, donors: new DonorService(config), }; } diff --git a/backend/src/routes/admin.ts b/backend/src/routes/admin.ts new file mode 100644 index 0000000..c2fc5a7 --- /dev/null +++ b/backend/src/routes/admin.ts @@ -0,0 +1,122 @@ +import { timingSafeEqual } from "node:crypto"; +import type { FastifyInstance } from "fastify"; +import { saveActiveTables } from "../services/state.js"; + +function safeEqual(a: string, b: string): boolean { + const ba = Buffer.from(a || ""); + const bb = Buffer.from(b || ""); + if (ba.length !== bb.length) return false; + return timingSafeEqual(ba, bb); +} + +/** + * Admin actions for the /crush33 area — all gated by the same PORTAL_PASSWORD + * that unlocks the portal. POST-only so the password never lands in a URL/log. + * + * POST /api/admin/status -> current event tables + record counts + * POST /api/admin/wipe -> delete all ticket + audit records + * POST /api/admin/switch-table -> point the app at different event table(s) + * POST /api/admin/donor-search -> admin-only donor directory search (PII) + */ +export async function adminRoutes(app: FastifyInstance): Promise { + const cfg = app.ctx.config; + + const gate = (req: any, reply: any): boolean => { + if (!cfg.PORTAL_PASSWORD) { + reply.code(404).send({ error: "admin_disabled" }); + return false; + } + const pw = (req.body ?? {}).password; + if (typeof pw !== "string" || !safeEqual(pw, cfg.PORTAL_PASSWORD)) { + reply.code(401).send({ error: "bad_password" }); + return false; + } + return true; + }; + + const rl = { config: { rateLimit: { max: 30, timeWindow: "1 minute" } } }; + + app.post("/api/admin/status", rl, async (req, reply) => { + if (!gate(req, reply)) return; + const [tickets, audit] = await Promise.all([ + app.ctx.nocodb.count().catch(() => -1), + app.ctx.audit.count().catch(() => -1), + ]); + return { + tickets: { tableId: app.ctx.nocodb.tableId, count: tickets }, + audit: { tableId: app.ctx.audit.currentTableId, count: audit, enabled: app.ctx.audit.enabled }, + // What .env would use if the override were cleared (for reference). + defaults: { ticketsTableId: cfg.NOCODB_TABLE_ID, auditTableId: cfg.NOCODB_AUDIT_TABLE_ID ?? null }, + }; + }); + + app.post("/api/admin/wipe", rl, async (req, reply) => { + if (!gate(req, reply)) return; + let ticketsDeleted = 0; + let auditDeleted = 0; + try { + ticketsDeleted = await app.ctx.nocodb.deleteAll(); + } catch (e: any) { + return reply.code(502).send({ error: "wipe_failed", detail: e?.message }); + } + try { + auditDeleted = await app.ctx.audit.deleteAll(); + } catch { + // Audit wipe is best-effort; tickets are the important part. + } + req.log.warn({ ticketsDeleted, auditDeleted }, "admin: wiped slate"); + return { ok: true, ticketsDeleted, auditDeleted }; + }); + + app.post("/api/admin/switch-table", rl, async (req, reply) => { + if (!gate(req, reply)) return; + const b = (req.body ?? {}) as { ticketsTableId?: string; auditTableId?: string }; + const ticketsTableId = String(b.ticketsTableId ?? "").trim(); + const auditTableId = String(b.auditTableId ?? "").trim(); + if (!ticketsTableId) { + return reply.code(400).send({ error: "missing_tickets_table" }); + } + + // Validate the new tickets table is reachable and has an Id primary key — + // switching to a PK-less table would make check-in updates hit every row. + const probe = await app.ctx.nocodb.probeTable(ticketsTableId); + if (!probe.ok) { + return reply.code(400).send({ error: "tickets_table_unreachable", status: probe.status }); + } + if (!probe.hasIdPk) { + return reply.code(400).send({ error: "tickets_table_no_id_pk" }); + } + if (auditTableId) { + const ap = await app.ctx.nocodb.probeTable(auditTableId); + if (!ap.ok) return reply.code(400).send({ error: "audit_table_unreachable", status: ap.status }); + } + + // Hot-swap the live clients, then persist so it survives a redeploy. + app.ctx.nocodb.setTableId(ticketsTableId); + app.ctx.audit.setTableId(auditTableId || app.ctx.audit.currentTableId); + saveActiveTables(cfg.STATE_DIR, { + ticketsTableId, + auditTableId: auditTableId || app.ctx.audit.currentTableId || undefined, + }); + req.log.warn({ ticketsTableId, auditTableId }, "admin: switched event table"); + return { + ok: true, + tickets: { tableId: app.ctx.nocodb.tableId }, + audit: { tableId: app.ctx.audit.currentTableId }, + }; + }); + + app.post("/api/admin/donor-search", rl, async (req, reply) => { + if (!gate(req, reply)) return; + if (!app.ctx.donors.enabled) return reply.code(404).send({ error: "donors_unavailable" }); + const q = String(((req.body ?? {}) as { query?: string }).query ?? "").trim(); + if (q.length < 2) return { results: [], query: q }; + try { + const results = await app.ctx.donors.search(q, 40); + return { results, query: q }; + } catch (e: any) { + req.log.error({ err: e }, "admin: donor search failed"); + return reply.code(502).send({ error: "search_failed", detail: e?.message }); + } + }); +} diff --git a/backend/src/server.ts b/backend/src/server.ts index 7895fe1..685e1a7 100644 --- a/backend/src/server.ts +++ b/backend/src/server.ts @@ -16,6 +16,7 @@ import { installRoutes } from "./routes/install.js"; import { webhookDocRoutes } from "./routes/webhookDoc.js"; import { publicLookupRoutes } from "./routes/publicLookup.js"; import { portalRoutes } from "./routes/portal.js"; +import { adminRoutes } from "./routes/admin.js"; export async function build() { const config = loadConfig(); @@ -40,6 +41,7 @@ export async function build() { await app.register(webhookDocRoutes); await app.register(publicLookupRoutes); await app.register(portalRoutes); + await app.register(adminRoutes); // Serve the exported Expo web build (if present) with SPA fallback. const webDir = config.WEB_DIR ?? join(process.cwd(), "web"); diff --git a/backend/src/services/audit.ts b/backend/src/services/audit.ts index 2782958..c6b3a29 100644 --- a/backend/src/services/audit.ts +++ b/backend/src/services/audit.ts @@ -34,7 +34,7 @@ export interface AuditRow extends AuditEntry { export class AuditLogger { private readonly base: string; private readonly token: string; - private readonly tableId: string | null; + private tableId: string | null; constructor(cfg: Pick) { this.base = cfg.NOCODB_BASE_URL.replace(/\/+$/, ""); @@ -46,10 +46,56 @@ export class AuditLogger { return this.tableId !== null; } + /** The audit table id (switchable at runtime by the admin action). */ + get currentTableId(): string | null { + return this.tableId; + } + setTableId(id: string | null): void { + this.tableId = id || null; + } + private get url(): string { return `${this.base}/api/v2/tables/${this.tableId}/records`; } + /** Total audit row count (cheap — reads pageInfo). */ + async count(): Promise { + if (!this.tableId) return 0; + const url = new URL(this.url); + url.searchParams.set("limit", "1"); + const res = await fetch(url.toString(), { + headers: { "xc-token": this.token, "Content-Type": "application/json" }, + }); + if (!res.ok) return 0; + const body: any = await res.json().catch(() => ({})); + return body?.pageInfo?.totalRows ?? (body?.list?.length ?? 0); + } + + /** Delete every audit row in the current table. Returns the count deleted. */ + async deleteAll(): Promise { + if (!this.tableId) return 0; + let total = 0; + for (;;) { + const url = new URL(this.url); + url.searchParams.set("limit", "1000"); + url.searchParams.set("fields", "Id"); + const res = await fetch(url.toString(), { + headers: { "xc-token": this.token, "Content-Type": "application/json" }, + }); + if (!res.ok) break; + const body: any = await res.json().catch(() => ({})); + const list = body?.list ?? []; + if (!list.length) break; + await fetch(this.url, { + method: "DELETE", + headers: { "xc-token": this.token, "Content-Type": "application/json" }, + body: JSON.stringify(list.map((r: any) => ({ Id: r.Id }))), + }); + total += list.length; + } + return total; + } + async log(entry: AuditEntry): Promise { if (!this.tableId) return; const sign = entry.people >= 0 ? "+" : ""; diff --git a/backend/src/services/donors.ts b/backend/src/services/donors.ts index 15909f0..46e5e53 100644 --- a/backend/src/services/donors.ts +++ b/backend/src/services/donors.ts @@ -1,5 +1,17 @@ import type { Config } from "../config.js"; +export interface DonorSearchResult { + name: string; + bearName: string; + email: string; + altEmail: string; + phone: string; + address: string; + lifetime: number | null; + tags: string[]; + source: "master" | "transactions"; +} + export interface DonorLookup { found: boolean; email: string; @@ -157,6 +169,67 @@ export class DonorService { }; } + /** + * Admin-only free-text donor search across the master list + transaction + * tables. Matches the query (substring, case-insensitive) against any + * name / email / phone / address / bear-name column each table exposes — + * columns are discovered from a sample row so it adapts to the schema. + * Results are de-duped by email (then name). PRIVACY: gate this to admins. + */ + async search(rawQuery: string, limit = 40): Promise { + const q = rawQuery.trim(); + if (!q || !this.enabled) return []; + const tables: { id: string | null; source: "master" | "transactions" }[] = [ + { id: this.masterId, source: "master" }, + { id: this.onlineId, source: "transactions" }, + { id: this.offlineId, source: "transactions" }, + ]; + const out = new Map(); + for (const t of tables) { + if (!t.id || out.size >= limit) continue; + let rows: any[]; + try { + rows = await this.searchTable(t.id, q, limit); + } catch { + continue; // a table without matching columns / transient error — skip + } + for (const r of rows) { + const res = mapDonorRow(r, t.source); + const key = (res.email || res.name || JSON.stringify(r)).toLowerCase(); + const existing = out.get(key); + // Prefer the master-list record (richer) when the same donor appears twice. + if (!existing || (existing.source === "transactions" && res.source === "master")) { + out.set(key, existing ? { ...res, lifetime: res.lifetime ?? existing.lifetime } : res); + } + if (out.size >= limit) break; + } + } + return [...out.values()].slice(0, limit); + } + + private colCache = new Map(); + + /** Discover the text columns worth searching (name/contact) from a sample row. */ + private async searchableColumns(tableId: string): Promise { + const cached = this.colCache.get(tableId); + if (cached) return cached; + const sample = await this.list(tableId, "", 1); + const keys = sample.length ? Object.keys(sample[0]) : []; + const want = /name|email|phone|mobile|cell|address|street|city|state|zip|postal|province|country|bear/i; + const skip = /[(),]/; // field names with filter-grammar chars can't be queried + const cols = keys.filter((k) => want.test(k) && !skip.test(k)); + this.colCache.set(tableId, cols); + return cols; + } + + private async searchTable(tableId: string, q: string, limit: number): Promise { + const cols = await this.searchableColumns(tableId); + if (!cols.length) return []; + const esc = q.replace(/[(),]/g, " "); + const where = cols.map((c) => `(${c},like,%${esc}%)`).join("~or"); + return this.list(tableId, where, limit); + } + /** * Total Paid donations for an email on/after `cutoff`, summed from the * transaction tables (the only dated source). Used for ticket-voucher @@ -183,6 +256,40 @@ function num(v: unknown): number { return Number.isFinite(n) ? n : 0; } +/** First non-empty value whose column name matches `rx`. */ +function pick(row: any, rx: RegExp): string { + for (const k of Object.keys(row)) if (rx.test(k) && row[k] != null && row[k] !== "") return String(row[k]); + return ""; +} +/** Join all non-empty values whose column name matches `rx` (e.g. address parts). */ +function pickAll(row: any, rx: RegExp): string { + const parts: string[] = []; + for (const k of Object.keys(row)) if (rx.test(k) && row[k] != null && row[k] !== "") parts.push(String(row[k])); + return [...new Set(parts)].join(", "); +} + +function mapDonorRow(r: any, source: "master" | "transactions"): DonorSearchResult { + const name = + r["Display Name"] || + r["Name"] || + [r["First Name"], r["Last Name"]].filter(Boolean).join(" ") || + r["Bear Name"] || + pick(r, /name/i) || + ""; + const lifetimeRaw = r["Total Donations"]; + return { + name: String(name), + bearName: String(r["Bear Name"] ?? ""), + email: String(r["Email"] ?? pick(r, /email/i)), + altEmail: String(r["Alternate Email"] ?? ""), + phone: pick(r, /phone|mobile|cell/i), + address: pickAll(r, /address|street|city|state|zip|postal|province|country/i), + lifetime: lifetimeRaw !== undefined && lifetimeRaw !== null && lifetimeRaw !== "" ? num(lifetimeRaw) : null, + tags: splitTags(r["Tags"]), + source, + }; +} + // Count a transaction unless it's explicitly not paid (refunded/failed/pending). function isPaid(row: any): boolean { const s = String(row["Payment Status"] ?? "").trim(); diff --git a/backend/src/services/nocodb.ts b/backend/src/services/nocodb.ts index f26f452..9e3416e 100644 --- a/backend/src/services/nocodb.ts +++ b/backend/src/services/nocodb.ts @@ -8,16 +8,24 @@ import { COL, type NocoRecord } from "../fields.js"; export class NocoDBClient { private readonly base: string; private readonly token: string; - private readonly tableId: string; + private _tableId: string; constructor(cfg: Pick) { this.base = cfg.NOCODB_BASE_URL.replace(/\/+$/, ""); this.token = cfg.NOCODB_API_TOKEN; - this.tableId = cfg.NOCODB_TABLE_ID; + this._tableId = cfg.NOCODB_TABLE_ID; + } + + /** The table this client currently reads/writes (switchable at runtime). */ + get tableId(): string { + return this._tableId; + } + setTableId(id: string): void { + this._tableId = id; } private get recordsUrl(): string { - return `${this.base}/api/v2/tables/${this.tableId}/records`; + return `${this.base}/api/v2/tables/${this._tableId}/records`; } private async request(url: string, init: RequestInit = {}): Promise { @@ -138,6 +146,47 @@ export class NocoDBClient { return out; } + /** Total record count in the current table (cheap — reads pageInfo). */ + async count(): Promise { + const url = new URL(this.recordsUrl); + url.searchParams.set("limit", "1"); + const body = await this.request(url.toString()); + return body?.pageInfo?.totalRows ?? (body?.list?.length ?? 0); + } + + /** Delete every record in the current table (paginated bulk delete). Returns + * the number deleted. Used by the admin "wipe slate" action. */ + async deleteAll(): Promise { + let total = 0; + for (;;) { + const rows = await this.list("", 1000); + if (!rows.length) break; + const ids = rows.map((r) => ({ Id: (r as any).Id })); + await this.request(this.recordsUrl, { method: "DELETE", body: JSON.stringify(ids) }); + total += rows.length; + } + return total; + } + + /** Reachability + primary-key probe for a candidate table id (admin switch). + * Returns { ok, hasIdPk }. hasIdPk is false only if rows exist without an Id. */ + async probeTable(tableId: string): Promise<{ ok: boolean; hasIdPk: boolean; status: number }> { + const url = new URL(`${this.base}/api/v2/tables/${tableId}/records`); + url.searchParams.set("limit", "1"); + try { + const res = await fetch(url.toString(), { + headers: { "xc-token": this.token, "Content-Type": "application/json" }, + }); + if (!res.ok) return { ok: false, hasIdPk: false, status: res.status }; + const body: any = await res.json().catch(() => ({})); + const list = body?.list ?? []; + const hasIdPk = list.length === 0 || "Id" in list[0]; + return { ok: true, hasIdPk, status: 200 }; + } catch { + return { ok: false, hasIdPk: false, status: 0 }; + } + } + /** Cheap connectivity probe for healthchecks. */ async ping(): Promise { const url = new URL(this.recordsUrl); diff --git a/backend/src/services/state.ts b/backend/src/services/state.ts new file mode 100644 index 0000000..b2cde2a --- /dev/null +++ b/backend/src/services/state.ts @@ -0,0 +1,32 @@ +import { readFileSync, writeFileSync, mkdirSync } from "node:fs"; +import { join } from "node:path"; + +/** + * Tiny persisted state, stored as JSON on a mounted volume (STATE_DIR). Used for + * the admin "switch event table" action so the choice survives a redeploy — + * otherwise the app would revert to the .env table IDs on every restart. + */ +export interface ActiveTables { + ticketsTableId: string; + auditTableId?: string; +} + +const FILE = "active-tables.json"; + +export function loadActiveTables(dir: string): ActiveTables | null { + try { + const raw = readFileSync(join(dir, FILE), "utf8"); + const parsed = JSON.parse(raw); + if (parsed && typeof parsed.ticketsTableId === "string" && parsed.ticketsTableId) { + return { ticketsTableId: parsed.ticketsTableId, auditTableId: parsed.auditTableId || undefined }; + } + } catch { + // No override or unreadable — fall back to .env config. + } + return null; +} + +export function saveActiveTables(dir: string, tables: ActiveTables): void { + mkdirSync(dir, { recursive: true }); + writeFileSync(join(dir, FILE), JSON.stringify(tables, null, 2), "utf8"); +} diff --git a/docker-compose.yml b/docker-compose.yml index 3668405..dc62d8d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,4 +19,11 @@ services: # host.docker.internal resolves to the host gateway. extra_hosts: - "host.docker.internal:host-gateway" + # Small writable volume for runtime state (the active event-table override + # set from the admin area), so it survives redeploys. + volumes: + - camptickets-data:/data restart: unless-stopped + +volumes: + camptickets-data: diff --git a/scripts/switch-event.sh b/scripts/switch-event.sh new file mode 100755 index 0000000..862ad54 --- /dev/null +++ b/scripts/switch-event.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +set -euo pipefail +# +# switch-event.sh — point the scanner app at a DIFFERENT NocoDB tickets (and +# optionally audit) table, e.g. to start a NEW event on a fresh table while +# keeping the old table intact for archive. Backs up backend/.env, updates it, +# and restarts the app container. The old table is never touched. +# +# Usage: +# scripts/switch-event.sh [AUDIT_TABLE_ID] +# +# FIRST create the new table(s): in the NocoDB UI, DUPLICATE the current table +# with "structure only" (no records). That preserves every column AND the Id +# primary key — critical, because updates against a table with no primary key +# would hit every row. Then grab the new table id from its URL/API and pass it +# here. (The app also fail-safes: it refuses to update a row that has no Id.) +# +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +ENV_FILE="$ROOT/backend/.env" +CONTAINER="${CONTAINER:-camptickets}" + +NEW_TICKETS="${1:-}" +NEW_AUDIT="${2:-}" +[ -n "$NEW_TICKETS" ] || { echo "Usage: $0 [AUDIT_TABLE_ID]" >&2; exit 1; } + +get() { grep -E "^$1=" "$ENV_FILE" | head -1 | cut -d= -f2-; } +BASE_URL="$(get NOCODB_BASE_URL)" +TOKEN="$(get NOCODB_API_TOKEN)" +CUR_TICKETS="$(get NOCODB_TABLE_ID)" +CUR_AUDIT="$(get NOCODB_AUDIT_TABLE_ID)" + +# Validate a table is reachable and (if it has rows) exposes an Id primary key. +check() { + local table="$1" tmp http + tmp="$(mktemp)" + http="$(curl -s -o "$tmp" -w '%{http_code}' -H "xc-token: $TOKEN" \ + "$BASE_URL/api/v2/tables/$table/records?limit=1")" + if [ "$http" != "200" ]; then + echo " ✗ $table not reachable (HTTP $http)"; rm -f "$tmp"; return 1 + fi + if ! python3 -c 'import sys,json; l=json.load(open(sys.argv[1]))["list"]; sys.exit(0 if (not l or "Id" in l[0]) else 1)' "$tmp"; then + echo " ✗ $table has rows without an Id primary key — refusing"; rm -f "$tmp"; return 1 + fi + rm -f "$tmp"; echo " ✓ $table reachable" +} + +echo "Validating new table(s) on $BASE_URL ..." +check "$NEW_TICKETS" || exit 1 +[ -n "$NEW_AUDIT" ] && { check "$NEW_AUDIT" || exit 1; } + +BK="$ENV_FILE.bak.$(date +%Y%m%d-%H%M%S)" +cp "$ENV_FILE" "$BK" +echo "Backed up env -> $BK" + +echo "Switching tables:" +echo " tickets: $CUR_TICKETS -> $NEW_TICKETS" +sed -i -E "s|^NOCODB_TABLE_ID=.*|NOCODB_TABLE_ID=$NEW_TICKETS|" "$ENV_FILE" +if [ -n "$NEW_AUDIT" ]; then + echo " audit: $CUR_AUDIT -> $NEW_AUDIT" + sed -i -E "s|^NOCODB_AUDIT_TABLE_ID=.*|NOCODB_AUDIT_TABLE_ID=$NEW_AUDIT|" "$ENV_FILE" +else + echo " audit: unchanged ($CUR_AUDIT) — pass a second arg to switch it too" +fi + +echo "Restarting $CONTAINER ..." +( cd "$ROOT" && docker compose up -d --force-recreate >/dev/null ) +sleep 3 + +echo "Now active:" +echo " NOCODB_TABLE_ID=$(get NOCODB_TABLE_ID)" +echo " NOCODB_AUDIT_TABLE_ID=$(get NOCODB_AUDIT_TABLE_ID)" +echo "Old tickets table $CUR_TICKETS kept intact. (env backup: $BK)" diff --git a/scripts/wipe-slate.sh b/scripts/wipe-slate.sh new file mode 100755 index 0000000..58fc3a8 --- /dev/null +++ b/scripts/wipe-slate.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +set -euo pipefail +# +# wipe-slate.sh — clear ALL ticket + audit records from the tables the scanner +# app currently uses, for a clean event run-through. Leaves the table SCHEMAS +# intact and does NOT touch donor data. Reads NocoDB creds from backend/.env. +# +# Usage: +# scripts/wipe-slate.sh # prompts for confirmation +# scripts/wipe-slate.sh --yes # skip the prompt (for automation) +# +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ENV_FILE="${ENV_FILE:-$SCRIPT_DIR/../backend/.env}" + +get() { grep -E "^$1=" "$ENV_FILE" | head -1 | cut -d= -f2-; } +BASE_URL="$(get NOCODB_BASE_URL)" +TOKEN="$(get NOCODB_API_TOKEN)" +TICKETS="$(get NOCODB_TABLE_ID)" +AUDIT="$(get NOCODB_AUDIT_TABLE_ID)" + +[ -n "$BASE_URL" ] && [ -n "$TOKEN" ] && [ -n "$TICKETS" ] || { + echo "Missing NocoDB config in $ENV_FILE" >&2; exit 1; } + +YES=0 +case "${1:-}" in -y|--yes) YES=1;; esac + +count() { + curl -s -H "xc-token: $TOKEN" "$BASE_URL/api/v2/tables/$1/records?limit=1" \ + | python3 -c 'import sys,json;print(json.load(sys.stdin).get("pageInfo",{}).get("totalRows",0))' +} + +echo "Target: $BASE_URL" +echo " tickets ($TICKETS): $(count "$TICKETS") records" +[ -n "$AUDIT" ] && echo " audit ($AUDIT): $(count "$AUDIT") records" + +if [ "$YES" -ne 1 ]; then + read -rp "Delete ALL of the above? This cannot be undone. [y/N] " ans + case "$ans" in y|Y|yes|YES) ;; *) echo "aborted"; exit 1;; esac +fi + +wipe() { + local label="$1" table="$2" total=0 ids n + while :; do + ids="$(curl -s -H "xc-token: $TOKEN" "$BASE_URL/api/v2/tables/$table/records?limit=1000&fields=Id" \ + | python3 -c 'import sys,json;print(json.dumps([{"Id":r["Id"]} for r in json.load(sys.stdin)["list"]]))')" + n="$(printf '%s' "$ids" | python3 -c 'import sys,json;print(len(json.load(sys.stdin)))')" + [ "$n" -eq 0 ] && break + curl -s -o /dev/null -X DELETE -H "xc-token: $TOKEN" -H "Content-Type: application/json" \ + "$BASE_URL/api/v2/tables/$table/records" --data "$ids" + total=$((total + n)) + done + echo " $label: deleted $total" +} + +wipe "tickets" "$TICKETS" +[ -n "$AUDIT" ] && wipe "audit" "$AUDIT" +echo "Done — slate is clean." From 1c8cb47209fc2694350b6fca424d73a0ddfb7e1f Mon Sep 17 00:00:00 2001 From: Hank Date: Thu, 23 Jul 2026 01:49:15 +0000 Subject: [PATCH 20/22] Move admin hub into the /crush33 page; drop the /comp app route MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The admin area belongs at /crush33 (the standalone, portal-password page — no app login), not an in-app /comp route I'd added unasked. - Rebuilt the /crush33 page into the full hub: password unlock → sidebar (Comp tickets · Donor lookup · Actions). Vanilla JS calling the same /api/portal + /api/admin endpoints. Actions has the danger cards + an "are you sure" modal spelling out exactly what happens. - Deleted app/app/comp.tsx (removes the /comp route). - Drawer "Admin (crush33)" now opens the /crush33 web page (Linking) instead of routing to /comp. Co-Authored-By: Claude Opus 4.8 (1M context) --- app/app/comp.tsx | 545 ----------------------------------- app/components/SideMenu.tsx | 15 +- backend/src/routes/portal.ts | 381 ++++++++++++++++++++---- 3 files changed, 328 insertions(+), 613 deletions(-) delete mode 100644 app/app/comp.tsx diff --git a/app/app/comp.tsx b/app/app/comp.tsx deleted file mode 100644 index 648af1e..0000000 --- a/app/app/comp.tsx +++ /dev/null @@ -1,545 +0,0 @@ -import { useState, useCallback, useEffect } from "react"; -import { - StyleSheet, - View, - Text, - TextInput, - Pressable, - ScrollView, - Image, - KeyboardAvoidingView, - Platform, - ActivityIndicator, -} from "react-native"; -import { SafeAreaView } from "react-native-safe-area-context"; -import { - portalVerify, - portalCreate, - adminStatus, - adminWipe, - adminSwitchTable, - adminDonorSearch, - AuthError, - type PortalTicket, - type AdminStatus, - type DonorSearchResult, -} from "../lib/api"; -import { useAuth } from "../lib/auth"; -import { useMenu } from "../lib/menu"; -import { theme } from "../lib/theme"; - -const TYPES = ["Guest", "Worker", "Performer", "Volunteer", "Speaker"]; -const TYPE_ICON: Record = { - Guest: "🎫", - Worker: "🛠️", - Performer: "🎭", - Volunteer: "🙌", - Speaker: "🎤", -}; - -type Section = "comp" | "donors" | "actions"; -const NAV: { key: Section; icon: string; label: string }[] = [ - { key: "comp", icon: "🎟️", label: "Comp\ntickets" }, - { key: "donors", icon: "🔎", label: "Donor\nlookup" }, - { key: "actions", icon: "⚠️", label: "Actions" }, -]; - -export default function AdminHub() { - const { operator } = useAuth(); - const { open: openMenu } = useMenu(); - const [password, setPassword] = useState(""); - const [unlocked, setUnlocked] = useState(false); - const [busy, setBusy] = useState(false); - const [error, setError] = useState(""); - const [section, setSection] = useState
    ("comp"); - - const relock = useCallback(() => { - setUnlocked(false); - setError("Password changed — unlock again."); - }, []); - - async function unlock() { - if (!password || busy) return; - setBusy(true); - setError(""); - try { - await portalVerify(password); - setUnlocked(true); - } catch (e: any) { - setError(e instanceof AuthError ? "Wrong password" : e?.message ?? "Failed"); - } finally { - setBusy(false); - } - } - - return ( - - - - - - Admin · crush33 - - - - {!unlocked ? ( - - - Admin-only area. Enter the shared portal password to unlock. - Portal password - - {!!error && {error}} - - {busy ? "Checking…" : "Unlock"} - - - - ) : ( - - - {NAV.map((n) => { - const active = section === n.key; - return ( - setSection(n.key)}> - {n.icon} - {n.label} - - ); - })} - - - - - {section === "comp" && } - {section === "donors" && } - {section === "actions" && } - - - - )} - - ); -} - -/* ---------------- Comp tickets ---------------- */ - -function CompSection({ password, operator, onRelock }: { password: string; operator: string | null; onRelock: () => void }) { - const [type, setType] = useState("Guest"); - const [name, setName] = useState(""); - const [email, setEmail] = useState(""); - const [busy, setBusy] = useState(false); - const [error, setError] = useState(""); - const [result, setResult] = useState(null); - - async function create() { - if (!name.trim() || !email.trim() || busy) return; - setBusy(true); - setError(""); - try { - const r = await portalCreate({ password, name: name.trim(), email: email.trim(), type, createdBy: operator ?? "" }); - setResult(r); - setName(""); - setEmail(""); - } catch (e: any) { - if (e instanceof AuthError) onRelock(); - else setError(e?.message ?? "Failed to create ticket"); - } finally { - setBusy(false); - } - } - - return ( - - Comp tickets - Entry-only tickets for guests & staff. - - Ticket type - - {TYPES.map((t) => ( - setType(t)}> - {(TYPE_ICON[t] ?? "🎫") + " " + t} - - ))} - - - Full name - - Email - - - {!!error && {error}} - - {busy ? "Creating…" : `Create ${type} ticket`} - - - {result && ( - - - {result.code} - {result.type} · {result.name} - {result.emailSent ? "✓ Emailed the ticket" : "Email not sent — screenshot this QR"} - - )} - - ); -} - -/* ---------------- Donor lookup ---------------- */ - -function DonorSection({ password, onRelock }: { password: string; onRelock: () => void }) { - const [query, setQuery] = useState(""); - const [busy, setBusy] = useState(false); - const [error, setError] = useState(""); - const [results, setResults] = useState(null); - - async function run() { - const q = query.trim(); - if (q.length < 2 || busy) return; - setBusy(true); - setError(""); - try { - const r = await adminDonorSearch(password, q); - setResults(r.results); - } catch (e: any) { - if (e instanceof AuthError) onRelock(); - else setError(e?.message ?? "Search failed"); - } finally { - setBusy(false); - } - } - - return ( - - Donor lookup - 🔒 Admin only · private donor info. Search by name, email, phone, address, bear name… - - - - - {busy ? "…" : "Search"} - - - - {!!error && {error}} - {results !== null && !busy && results.length === 0 && No donors match “{query.trim()}”.} - - {results?.map((d, i) => ( - - - {d.name || d.email || "(unnamed)"} - {d.lifetime != null && {money(d.lifetime)}} - - {!!d.bearName && 🐻 {d.bearName}} - {!!d.email && ✉️ {d.email}} - {!!d.altEmail && ✉️ {d.altEmail} (alt)} - {!!d.phone && 📞 {d.phone}} - {!!d.address && 🏠 {d.address}} - - {d.source === "master" ? "directory" : "transactions"} - {d.tags.map((t) => ( - {t} - ))} - - - ))} - - ); -} - -/* ---------------- Actions (danger zone) ---------------- */ - -function ActionsSection({ password, onRelock }: { password: string; onRelock: () => void }) { - const [status, setStatus] = useState(null); - const [loading, setLoading] = useState(false); - const [msg, setMsg] = useState(""); - const [confirm, setConfirm] = useState(null); - const [busy, setBusy] = useState(false); - const [newTickets, setNewTickets] = useState(""); - const [newAudit, setNewAudit] = useState(""); - - const refresh = useCallback(async () => { - setLoading(true); - try { - setStatus(await adminStatus(password)); - } catch (e: any) { - if (e instanceof AuthError) onRelock(); - } finally { - setLoading(false); - } - }, [password, onRelock]); - - // Load status the first time this section renders. - useEffect(() => { - refresh(); - }, [refresh]); - - async function doWipe() { - setBusy(true); - setMsg(""); - try { - const r = await adminWipe(password); - setMsg(`✓ Wiped ${r.ticketsDeleted} tickets and ${r.auditDeleted} audit rows.`); - setConfirm(null); - refresh(); - } catch (e: any) { - if (e instanceof AuthError) onRelock(); - else setMsg(e?.message ?? "Wipe failed"); - } finally { - setBusy(false); - } - } - - async function doSwitch() { - if (!newTickets.trim()) return; - setBusy(true); - setMsg(""); - try { - const r = await adminSwitchTable(password, newTickets.trim(), newAudit.trim() || undefined); - setMsg(`✓ Now using tickets table ${r.tickets.tableId}.`); - setConfirm(null); - setNewTickets(""); - setNewAudit(""); - refresh(); - } catch (e: any) { - if (e instanceof AuthError) onRelock(); - else setMsg(e?.message ?? "Switch failed"); - } finally { - setBusy(false); - } - } - - return ( - - Actions - Event-management tools. These change live data — read the warnings. - - {/* Current status */} - - - Active event table - - {loading ? "…" : "↻"} - - - {status ? ( - <> - tickets: {status.tickets.tableId} · {status.tickets.count} records - audit: {status.audit.tableId ?? "—"} · {status.audit.count} records - - ) : ( - {loading ? "loading…" : "—"} - )} - - - {!!msg && {msg}} - - {/* Wipe slate */} - - 🧹 Wipe the slate clean - - Permanently deletes every ticket and every check-in in the active event - table. Use this to reset before a run-through or a fresh event. - - • Does NOT affect donor data. - • Cannot be undone. - { setMsg(""); setConfirm("wipe"); }}> - Wipe slate… - - - - {/* Switch table */} - - 🔀 Switch event table - - Point the scanner at a different NocoDB table — e.g. to start a new event on - a fresh table while keeping the current one intact. - - • Create the new table first (duplicate the current one's structure in NocoDB — keep the Id column). - • The current event's data is NOT deleted, just no longer shown. - New tickets table ID - - New audit table ID (optional) - - { setMsg(""); setConfirm("switch"); }} disabled={!newTickets.trim()}> - Switch table… - - - - {confirm === "wipe" && ( - setConfirm(null)} - /> - )} - {confirm === "switch" && ( - setConfirm(null)} - /> - )} - - ); -} - -function ConfirmModal({ - title, - lines, - confirmLabel, - busy, - onConfirm, - onCancel, -}: { - title: string; - lines: string[]; - confirmLabel: string; - busy: boolean; - onConfirm: () => void; - onCancel: () => void; -}) { - return ( - - - ⚠️ - {title} - {lines.map((l, i) => ( - {l} - ))} - - {busy ? : {confirmLabel}} - - - Cancel - - - - ); -} - -function money(n: number): string { - return "$" + Math.round(n).toLocaleString(); -} - -const styles = StyleSheet.create({ - root: { flex: 1, backgroundColor: theme.bg }, - topbar: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingHorizontal: 16, paddingVertical: 10 }, - brand: { color: theme.text, fontSize: 18, fontWeight: "700" }, - hamburger: { color: theme.text, fontSize: 26, fontWeight: "700" }, - - body: { flex: 1, flexDirection: "row" }, - sidebar: { width: 84, backgroundColor: theme.card, borderRightWidth: 1, borderRightColor: theme.cardBorder, paddingTop: 8 }, - navItem: { paddingVertical: 14, alignItems: "center", gap: 4, borderLeftWidth: 3, borderLeftColor: "transparent" }, - navItemOn: { backgroundColor: theme.bg, borderLeftColor: theme.primary }, - navIcon: { fontSize: 22 }, - navLabel: { color: theme.textDim, fontSize: 11, fontWeight: "700", textAlign: "center", lineHeight: 13 }, - navLabelOn: { color: theme.text }, - content: { flex: 1 }, - pad: { padding: 16, paddingBottom: 48 }, - - h1: { color: theme.text, fontSize: 22, fontWeight: "800", marginBottom: 2 }, - sub: { color: theme.textDim, fontSize: 13, lineHeight: 19, marginBottom: 8 }, - lead: { color: theme.textDim, fontSize: 15, lineHeight: 21, marginBottom: 8 }, - label: { color: theme.textDim, fontSize: 13, marginTop: 14, marginBottom: 6 }, - input: { backgroundColor: theme.card, borderWidth: 1, borderColor: theme.cardBorder, borderRadius: 12, paddingHorizontal: 14, paddingVertical: 12, color: theme.text, fontSize: 16, marginBottom: 2 }, - error: { color: theme.dangerBright, marginTop: 12, fontSize: 14, fontWeight: "600" }, - msg: { color: theme.successBright, marginTop: 10, fontSize: 14, fontWeight: "700" }, - bold: { fontWeight: "800", color: theme.text }, - - btn: { backgroundColor: theme.successBright, borderRadius: 13, paddingVertical: 15, alignItems: "center", marginTop: 18 }, - btnOff: { opacity: 0.4 }, - btnText: { color: "#06210f", fontSize: 18, fontWeight: "800" }, - - types: { flexDirection: "row", flexWrap: "wrap", gap: 8 }, - typePill: { backgroundColor: theme.card, borderWidth: 1, borderColor: theme.cardBorder, borderRadius: 999, paddingHorizontal: 13, paddingVertical: 8 }, - typePillOn: { backgroundColor: theme.primary, borderColor: theme.primary }, - typePillText: { color: theme.textDim, fontSize: 13, fontWeight: "700" }, - typePillTextOn: { color: "#fff" }, - - result: { marginTop: 22, alignItems: "center", backgroundColor: theme.card, borderWidth: 1, borderColor: theme.cardBorder, borderRadius: 16, padding: 20 }, - qr: { width: 200, height: 200, backgroundColor: "#fff", borderRadius: 10 }, - rcode: { color: theme.successBright, fontSize: 22, fontWeight: "800", letterSpacing: 2, marginTop: 12 }, - rwho: { color: theme.text, fontSize: 16, marginTop: 4 }, - rmail: { color: theme.textDim, fontSize: 13, marginTop: 8 }, - - searchRow: { flexDirection: "row", gap: 8, alignItems: "center", marginTop: 8 }, - searchBtn: { backgroundColor: theme.primary, borderRadius: 12, paddingHorizontal: 16, paddingVertical: 13 }, - searchBtnText: { color: "#fff", fontWeight: "800", fontSize: 15 }, - donorCard: { backgroundColor: theme.card, borderWidth: 1, borderColor: theme.cardBorder, borderRadius: 12, padding: 14, marginTop: 12 }, - donorHead: { flexDirection: "row", justifyContent: "space-between", alignItems: "center" }, - donorName: { color: theme.text, fontSize: 17, fontWeight: "800", flex: 1 }, - donorAmt: { color: theme.successBright, fontSize: 16, fontWeight: "800", marginLeft: 8 }, - donorLine: { color: theme.textDim, fontSize: 14, marginTop: 3 }, - donorTags: { flexDirection: "row", flexWrap: "wrap", gap: 6, marginTop: 8, alignItems: "center" }, - donorSource: { color: theme.textDim, fontSize: 11, fontWeight: "700", textTransform: "uppercase", backgroundColor: theme.bg, borderWidth: 1, borderColor: theme.cardBorder, borderRadius: 6, paddingHorizontal: 6, paddingVertical: 2 }, - donorTag: { color: theme.text, fontSize: 12, backgroundColor: theme.primaryDark, borderRadius: 6, paddingHorizontal: 7, paddingVertical: 2 }, - - statusBox: { backgroundColor: theme.card, borderWidth: 1, borderColor: theme.cardBorder, borderRadius: 12, padding: 14, marginTop: 4 }, - statusRow: { flexDirection: "row", justifyContent: "space-between", alignItems: "center" }, - statusLabel: { color: theme.textDim, fontSize: 12, fontWeight: "700", textTransform: "uppercase", letterSpacing: 0.5 }, - refresh: { color: theme.text, fontSize: 20 }, - statusVal: { color: theme.text, fontSize: 14, marginTop: 6, fontFamily: Platform.OS === "ios" ? "Menlo" : "monospace" }, - - dangerCard: { backgroundColor: "#241717", borderWidth: 1, borderColor: theme.danger, borderRadius: 14, padding: 16, marginTop: 18 }, - dangerTitle: { color: "#ff9a9a", fontSize: 17, fontWeight: "800", marginBottom: 6 }, - dangerBody: { color: "#e9cfcf", fontSize: 14, lineHeight: 20 }, - dangerBullet: { color: "#d9b8b8", fontSize: 13, lineHeight: 19, marginTop: 4 }, - redBtn: { backgroundColor: theme.dangerBright, borderRadius: 12, paddingVertical: 14, alignItems: "center", marginTop: 16 }, - redBtnText: { color: "#fff", fontSize: 16, fontWeight: "800" }, - - modalScrim: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0, backgroundColor: "rgba(0,0,0,0.72)", alignItems: "center", justifyContent: "center", padding: 24 }, - modalCard: { backgroundColor: "#1a1010", borderWidth: 2, borderColor: theme.dangerBright, borderRadius: 18, padding: 22, width: "100%", maxWidth: 380 }, - modalWarn: { fontSize: 40, textAlign: "center" }, - modalTitle: { color: "#fff", fontSize: 20, fontWeight: "900", textAlign: "center", marginTop: 4, marginBottom: 12 }, - modalLine: { color: "#f0d9d9", fontSize: 14, lineHeight: 20 }, - cancelBtn: { paddingVertical: 14, alignItems: "center", marginTop: 6 }, - cancelText: { color: theme.textDim, fontSize: 16, fontWeight: "700" }, -}); diff --git a/app/components/SideMenu.tsx b/app/components/SideMenu.tsx index 890027b..a91600e 100644 --- a/app/components/SideMenu.tsx +++ b/app/components/SideMenu.tsx @@ -1,13 +1,16 @@ import { useEffect, useRef } from "react"; -import { Animated, StyleSheet, View, Text, Pressable, Easing, useWindowDimensions } from "react-native"; +import { Animated, StyleSheet, View, Text, Pressable, Easing, useWindowDimensions, Linking, Platform } from "react-native"; import { router, useSegments } from "expo-router"; import { useAuth } from "../lib/auth"; import { theme } from "../lib/theme"; -const ITEMS: { label: string; icon: string; route: string; seg: string }[] = [ +// The admin hub is the standalone /crush33 web page (not an app route). +const CRUSH_URL = Platform.OS === "web" ? "/crush33" : "https://scan.beartariacampgrounds.com/crush33"; + +const ITEMS: { label: string; icon: string; route: string; seg: string; external?: string }[] = [ { label: "Scanner", icon: "📷", route: "/", seg: "" }, { label: "Event report", icon: "📊", route: "/stats", seg: "stats" }, - { label: "Admin (crush33)", icon: "🔐", route: "/comp", seg: "comp" }, + { label: "Admin (crush33)", icon: "🔐", route: "", seg: "__admin", external: CRUSH_URL }, { label: "Banquet lookup", icon: "🍽️", route: "/admin", seg: "admin" }, ]; @@ -32,8 +35,12 @@ export default function SideMenu({ visible, onClose }: { visible: boolean; onClo ]).start(); }, [visible, panelW, tx, fade]); - const go = (item: { route: string; seg: string }) => { + const go = (item: { route: string; seg: string; external?: string }) => { onClose(); + if (item.external) { + Linking.openURL(item.external).catch(() => {}); + return; + } if (item.seg !== current) router.replace(item.route as any); }; diff --git a/backend/src/routes/portal.ts b/backend/src/routes/portal.ts index 8c55c0e..b6efcba 100644 --- a/backend/src/routes/portal.ts +++ b/backend/src/routes/portal.ts @@ -103,92 +103,345 @@ const PAGE = ` -Camp Scan — Comp Tickets +Camp Scan — Admin (crush33) -
    -
    - -

    Comp Ticket Portal

    -

    Entry-only tickets for workers & guests

    -
    +
    + +

    Admin · crush33

    +

    Admin-only area. Enter the shared portal password.

    + + +
    +
    - - +
    +
    +
    🐻 Admin · crush33
    +
    Lock 🔒
    +
    +
    +
    + + + +
    +
    + +
    +

    Comp tickets

    +

    Entry-only tickets for guests & staff.

    + +
    + 🎫 Guest🛠️ Worker🎭 Performer🙌 Volunteer🎤 Speaker +
    + + + + + +
    +
    + Ticket QR +
    +
    +
    +
    +
    - - + +
    +

    Donor lookup

    +

    🔒 Admin only · private donor info. Search by name, email, phone, address, bear name…

    +
    + + +
    +
    +
    +
    - - + +
    +

    Actions

    +

    Event-management tools. These change live data — read the warnings.

    +
    +
    Active event table
    +
    loading…
    +
    +
    - - +
    +

    🧹 Wipe the slate clean

    +

    Permanently deletes every ticket and every check-in in the active event table. Use before a run-through or a fresh event.

    +
    • Does NOT affect donor data.
    • Cannot be undone.
    + +
    - -
    +
    +

    🔀 Switch event table

    +

    Point the scanner at a different NocoDB table — start a new event on a fresh table while keeping the current one intact.

    +
    • Create the new table first (duplicate the current one's structure in NocoDB — keep the Id column).
    • The current event's data is NOT deleted, just no longer shown.
    + + + + + +
    +
    +
    +
    +
    -
    - Ticket QR -
    -
    -
    - +
    +
    `; From efe331a77ace4f6c8c6b84a36e3da4f5ea95aa84 Mon Sep 17 00:00:00 2001 From: Hank Date: Thu, 23 Jul 2026 01:58:08 +0000 Subject: [PATCH 21/22] Hide /crush33 from the staff drawer (admin-only URL) The admin hub link was showing in the app side menu; removed it so it isn't surfaced to gate staff. /crush33 is reached by URL only. Co-Authored-By: Claude Opus 4.8 (1M context) --- app/components/SideMenu.tsx | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/app/components/SideMenu.tsx b/app/components/SideMenu.tsx index a91600e..db0ca3c 100644 --- a/app/components/SideMenu.tsx +++ b/app/components/SideMenu.tsx @@ -1,16 +1,14 @@ import { useEffect, useRef } from "react"; -import { Animated, StyleSheet, View, Text, Pressable, Easing, useWindowDimensions, Linking, Platform } from "react-native"; +import { Animated, StyleSheet, View, Text, Pressable, Easing, useWindowDimensions } from "react-native"; import { router, useSegments } from "expo-router"; import { useAuth } from "../lib/auth"; import { theme } from "../lib/theme"; -// The admin hub is the standalone /crush33 web page (not an app route). -const CRUSH_URL = Platform.OS === "web" ? "/crush33" : "https://scan.beartariacampgrounds.com/crush33"; - -const ITEMS: { label: string; icon: string; route: string; seg: string; external?: string }[] = [ +// Note: the /crush33 admin hub is intentionally NOT listed here — it's an +// admin-only URL, not surfaced to gate staff in the app drawer. +const ITEMS: { label: string; icon: string; route: string; seg: string }[] = [ { label: "Scanner", icon: "📷", route: "/", seg: "" }, { label: "Event report", icon: "📊", route: "/stats", seg: "stats" }, - { label: "Admin (crush33)", icon: "🔐", route: "", seg: "__admin", external: CRUSH_URL }, { label: "Banquet lookup", icon: "🍽️", route: "/admin", seg: "admin" }, ]; @@ -35,12 +33,8 @@ export default function SideMenu({ visible, onClose }: { visible: boolean; onClo ]).start(); }, [visible, panelW, tx, fade]); - const go = (item: { route: string; seg: string; external?: string }) => { + const go = (item: { route: string; seg: string }) => { onClose(); - if (item.external) { - Linking.openURL(item.external).catch(() => {}); - return; - } if (item.seg !== current) router.replace(item.route as any); }; From bc93ef43f7277c5bc234b7c780b46332ff2dd70a Mon Sep 17 00:00:00 2001 From: Hank Date: Thu, 23 Jul 2026 02:01:30 +0000 Subject: [PATCH 22/22] crush33: back-to-scanner links + release v0.3.0 (versionCode 3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added "← Back to the scan app" on the crush33 unlock screen and a "← Scanner" link in the admin hub top bar (both -> /). v0.3.0 rolls up everything since v0.2.0: the /crush33 admin hub (sidebar, admin-only donor lookup, wipe/switch danger zone with confirm modals), removal of the /comp route, drawer no longer shows crush33, the customer_name / voucher-count / ticketless-order webhook fixes, ice bag fix, and the Adults/Youth/Kids gate panel. Co-Authored-By: Claude Opus 4.8 (1M context) --- app/app.json | 4 ++-- backend/src/routes/portal.ts | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/app.json b/app/app.json index ecfabbc..146efd3 100644 --- a/app/app.json +++ b/app/app.json @@ -2,7 +2,7 @@ "expo": { "name": "Camp Scan", "slug": "camptickets", - "version": "0.2.0", + "version": "0.3.0", "orientation": "portrait", "scheme": "campscan", "userInterfaceStyle": "automatic", @@ -10,7 +10,7 @@ "icon": "./assets/icon.png", "android": { "package": "top.mowden.campscan", - "versionCode": 2, + "versionCode": 3, "adaptiveIcon": { "foregroundImage": "./assets/adaptive-icon.png", "backgroundColor": "#0f1a12" diff --git a/backend/src/routes/portal.ts b/backend/src/routes/portal.ts index b6efcba..e8f9d75 100644 --- a/backend/src/routes/portal.ts +++ b/backend/src/routes/portal.ts @@ -126,6 +126,9 @@ const PAGE = ` #unlock .sub { color: #9db3a4; font-size: 14px; } #unlock input { text-align: center; margin-top: 18px; } #unlock .btn { width: 100%; margin-top: 16px; } + .backlink { display: inline-block; margin-top: 18px; color: #9db3a4; font-size: 14px; text-decoration: none; } + .backlink:hover { color: #eaf2ec; } + .top-back { margin-top: 0; } /* Hub */ #hub { display: none; min-height: 100vh; } @@ -194,10 +197,12 @@ const PAGE = `
    +
    ← Back to the scan app
    + ← Scanner
    🐻 Admin · crush33
    Lock 🔒