From f23108cda3e2bce0809b2ba6cd2b2883dce492a8 Mon Sep 17 00:00:00 2001 From: Amirhossein Khalili Date: Wed, 20 May 2026 09:46:17 +0330 Subject: [PATCH] refactor(all): migrate from React to Next.js --- .dockerignore | 5 + .env.sample | 4 +- .gitignore | 1 + README.md | 46 +- bun.lockb | Bin 197327 -> 0 bytes eslint.config.js | 8 +- index.html | 22 - next-env.d.ts | 6 + next.config.ts | 25 + nginx.conf | 33 - package-lock.json | 2458 ++++++----------- package.json | 26 +- public/robots.txt | 14 - src/App.tsx | 72 - src/app/about/page.tsx | 65 + src/app/admin/events/[id]/edit/page.tsx | 11 + src/app/admin/events/[id]/page.tsx | 11 + src/app/admin/events/page.tsx | 11 + src/app/admin/layout.tsx | 10 + src/app/admin/page.tsx | 5 + src/app/admin/users/page.tsx | 11 + src/app/auth/page.tsx | 11 + src/app/blog/[slug]/page.tsx | 156 ++ src/app/blog/page.tsx | 51 + src/app/events/[slug]/page.tsx | 115 + src/app/events/[slug]/success/page.tsx | 11 + src/app/events/page.tsx | 51 + src/app/layout.tsx | 34 + src/app/logout/page.tsx | 11 + src/app/not-found.tsx | 19 + src/app/page.tsx | 56 + src/app/payments/result/page.tsx | 16 + src/app/profile/page.tsx | 11 + src/app/reset-password/[token]/page.tsx | 11 + src/app/reset-password/page.tsx | 11 + src/app/robots.ts | 23 + src/app/sitemap.ts | 54 + src/app/verify-email/[token]/page.tsx | 11 + src/components/Footer.tsx | 136 +- src/components/Layout.tsx | 15 - src/components/Navbar.tsx | 6 +- src/components/ScrollToTop.tsx | 36 - src/components/ThemeProvider.tsx | 57 +- src/components/providers.tsx | 32 + src/components/ui/badge.tsx | 1 - src/components/ui/button.tsx | 1 - src/components/ui/form.tsx | 1 - src/components/ui/navigation-menu.tsx | 1 - src/components/ui/sidebar.tsx | 1 - src/components/ui/sonner.tsx | 1 - src/components/ui/toggle.tsx | 1 - src/contexts/AuthContext.tsx | 1 - src/lib/api.ts | 48 +- src/lib/helmet.tsx | 9 + src/lib/public-api.ts | 103 + src/lib/router.tsx | 143 + src/lib/site.ts | 17 + src/lib/types.ts | 16 +- src/lib/utils.ts | 2 +- src/main.tsx | 11 - src/pages/Events.tsx | 229 -- src/pages/Index.tsx | 14 - src/pages/NotFound.tsx | 25 - src/{pages => views}/AboutUs.tsx | 4 +- src/{pages => views}/AdminEventDetail.tsx | 4 +- src/{pages => views}/AdminEventEdit.tsx | 27 +- src/{pages => views}/AdminEvents.tsx | 50 +- src/{pages => views}/AdminLayout.tsx | 11 +- src/{pages => views}/AdminUsers.tsx | 2 + src/{pages => views}/Auth.tsx | 6 +- src/{pages => views}/Blog.tsx | 72 +- src/{pages => views}/EventDetail.tsx | 501 ++-- src/{pages => views}/EventFreeSuccessPage.tsx | 6 +- src/views/Events.tsx | 262 ++ src/{pages => views}/Home.tsx | 4 +- src/{pages => views}/Logout.tsx | 4 +- src/{pages => views}/PaymentResult.tsx | 14 +- src/{pages => views}/Profile.tsx | 11 +- src/{pages => views}/ResetPasswordConfirm.tsx | 4 +- src/{pages => views}/ResetPasswordRequest.tsx | 2 + src/{pages => views}/VerifyEmail.tsx | 4 +- src/vite-env.d.ts | 1 - tsconfig.app.json | 30 - tsconfig.json | 48 +- tsconfig.node.json | 22 - vite.config.ts | 18 - 86 files changed, 2831 insertions(+), 2679 deletions(-) create mode 100644 .dockerignore delete mode 100644 bun.lockb delete mode 100644 index.html create mode 100644 next-env.d.ts create mode 100644 next.config.ts delete mode 100644 nginx.conf delete mode 100644 public/robots.txt delete mode 100644 src/App.tsx create mode 100644 src/app/about/page.tsx create mode 100644 src/app/admin/events/[id]/edit/page.tsx create mode 100644 src/app/admin/events/[id]/page.tsx create mode 100644 src/app/admin/events/page.tsx create mode 100644 src/app/admin/layout.tsx create mode 100644 src/app/admin/page.tsx create mode 100644 src/app/admin/users/page.tsx create mode 100644 src/app/auth/page.tsx create mode 100644 src/app/blog/[slug]/page.tsx create mode 100644 src/app/blog/page.tsx create mode 100644 src/app/events/[slug]/page.tsx create mode 100644 src/app/events/[slug]/success/page.tsx create mode 100644 src/app/events/page.tsx create mode 100644 src/app/layout.tsx create mode 100644 src/app/logout/page.tsx create mode 100644 src/app/not-found.tsx create mode 100644 src/app/page.tsx create mode 100644 src/app/payments/result/page.tsx create mode 100644 src/app/profile/page.tsx create mode 100644 src/app/reset-password/[token]/page.tsx create mode 100644 src/app/reset-password/page.tsx create mode 100644 src/app/robots.ts create mode 100644 src/app/sitemap.ts create mode 100644 src/app/verify-email/[token]/page.tsx delete mode 100644 src/components/Layout.tsx delete mode 100644 src/components/ScrollToTop.tsx create mode 100644 src/components/providers.tsx create mode 100644 src/lib/helmet.tsx create mode 100644 src/lib/public-api.ts create mode 100644 src/lib/router.tsx create mode 100644 src/lib/site.ts delete mode 100644 src/main.tsx delete mode 100644 src/pages/Events.tsx delete mode 100644 src/pages/Index.tsx delete mode 100644 src/pages/NotFound.tsx rename src/{pages => views}/AboutUs.tsx (99%) rename src/{pages => views}/AdminEventDetail.tsx (99%) rename src/{pages => views}/AdminEventEdit.tsx (92%) rename src/{pages => views}/AdminEvents.tsx (89%) rename src/{pages => views}/AdminLayout.tsx (86%) rename src/{pages => views}/AdminUsers.tsx (99%) rename src/{pages => views}/Auth.tsx (99%) rename src/{pages => views}/Blog.tsx (62%) rename src/{pages => views}/EventDetail.tsx (53%) rename src/{pages => views}/EventFreeSuccessPage.tsx (98%) create mode 100644 src/views/Events.tsx rename src/{pages => views}/Home.tsx (98%) rename src/{pages => views}/Logout.tsx (94%) rename src/{pages => views}/PaymentResult.tsx (97%) rename src/{pages => views}/Profile.tsx (99%) rename src/{pages => views}/ResetPasswordConfirm.tsx (97%) rename src/{pages => views}/ResetPasswordRequest.tsx (99%) rename src/{pages => views}/VerifyEmail.tsx (98%) delete mode 100644 src/vite-env.d.ts delete mode 100644 tsconfig.app.json delete mode 100644 tsconfig.node.json delete mode 100644 vite.config.ts diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..61f6bf4 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +.git +.next +node_modules +npm-debug.log +dist diff --git a/.env.sample b/.env.sample index 2c721e5..a431a2f 100644 --- a/.env.sample +++ b/.env.sample @@ -1,2 +1,2 @@ -VITE_API_BASE_URL=https://api.east-guilan-ce.ir - +NEXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8000 +NEXT_PUBLIC_SITE_URL=http://localhost:8080 diff --git a/.gitignore b/.gitignore index a0377b4..ffe15f1 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ pnpm-debug.log* lerna-debug.log* node_modules +.next dist dist-ssr .env diff --git a/README.md b/README.md index dd05475..e22204a 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,41 @@ # Frontend ## Stack -- Vite + React 18 with TypeScript. -- `@tanstack/react-query` for data fetching and caching. -- shadcn/ui primitives (button, card, tabs, dialog, etc.) with Tailwind CSS. -- Sonner & Toast UI for notifications, Markdown rendering, RTL layout, and Persian-digit helpers. +- Next.js App Router with React 18 and TypeScript. +- `@tanstack/react-query` for client-side authenticated flows. +- Tailwind CSS and shadcn/ui components. +- `next-themes`, Sonner, and toast helpers for RTL UI and notifications. + +## Environment +Copy `.env.sample` to `.env`. + +Required variables: +- `NEXT_PUBLIC_API_BASE_URL` +- `NEXT_PUBLIC_SITE_URL` ## Development - -### Install dependencies ```bash npm install +npm run dev ``` -### Configure API base URL -```bash -cp .env.sample .env -``` +The local dev server runs on `http://localhost:8080`. -### Run dev server -```bash -npm run dev -- --host -``` - -### Production build +## Production build ```bash npm run build +npm run start ``` -The Vite build reads `VITE_API_BASE_URL` from `.env`. +The production runtime serves on port `3000` inside Docker. Dockerfiles live only in `guilan-ace-deployment`. -## Features -- **Public site**: homepage, events list/detail, blog list, auth flows, profile, payments. -- **Admin dashboard**: staff-only portal with vertical tabs, user filtering, event filtering, popup detail with registrations/payments, and inline event editing/deletion. -- **Utils**: Persian digit formatting, price conversion (Rial → Toman), shared API client with JWT token refresh handling, and helper components (scroll area, table, dialog). +## Routes +- Public SEO pages: `/`, `/about`, `/blog`, `/blog/[slug]`, `/events`, `/events/[slug]` +- Client-heavy flows: `/auth`, `/profile`, `/logout`, `/payments/result`, `/reset-password/*`, `/verify-email/*` +- Admin: `/admin/*` -## Testing & linting +## Validation ```bash npm run lint +npm run build ``` - -JavaScript/TypeScript linting is configured through ESLint + `typescript-eslint`. Run lint before commits to keep code healthy. diff --git a/bun.lockb b/bun.lockb deleted file mode 100644 index d3914e8476ac7bcf7821f221922c3af9816eb903..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 197327 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

y2%D`EkutC#5qcdQP^usjju5A?>EK zr|k)4t^ncbe4k^O!7(@Zg3{V>(^qFvU@mqt1D-_s(uE48Ls z2nao@*HZg><*VcUbGui(Up9QA(&0(tzTB9Wxom{Xk_8`>ixs)tG&@sPb3bm!q1(NR{5WENN+jT~xOQ6c#B(DY*OH{_XOVwL{+eR4`Ew&N;i6NEGD5fh{rqrwZM@(x&c@i#UfrGA=kIq(WnSXKhrUAJJLTSgiWb`zqB7Dm zZ=>hT`kV(1g=M4iBx~05wWb`+k5z4xim$jB+NAxVQ=nMcC&*x9TEwk;m-Y`c3lu+{ zHtuO*-1=FMB0g>1XmqjR_-u(gpEA5p<~)A0eVfAB85<6~_qZTiHGQk(hxFaYoW3R0 zIi)XWjDI-1wt8R5#m3Ux8Rm8E%QUUU=Qf*FdU;(_dKbCjp8rXK*)6pnW^NQTx@T#u zB#>A=cg(6(l_{PpCkhU9yOTEh`xMtSzGTA&Da#u*)8F5f7u$WP-7v~J$Z7u6q!jUi zF48vA%P;#Z=~@`+^6erL5%@7@AVPNA2L&KK@i-!ID-^0Lp(dEVpM zI&TQ?_6sMB+_5-Vf&Tb1G`R-g}vw|+kbKg6L$DGtB zJ*l~Ry?eN=y9UX-i!Pd<_}7$WtS_&u43N`GBj;{%Zjo&>NGmVfaeQ-`)n49-7e8HC zYV$Dc!6|ok_pNav3C<5s+Iy1yOD$*^&%4UNY5!ODG4UZC*2-z-=R0f{4VdAytz5Bc zzk`xgAeYe8X)QtqFD8*Z`keVb+f}&3%sKjHoXZcf%8%+t6Ky+M7bc9;7qZxkS~y8#lf`em2>|4l5cn2pI{f~HhhQvw7egOMiiL{rJdS;Q(|Gg+Hf&Nk!A7@SI?|@KW*r% zxa##|=d2xFYM{#(reED{mv!nx3&a0~U~2+7m*>=<46hdqP2X1O@oL?y^lA=x&h3wI zQsjAD42C8=7Y~3kJg+nGIhz$B{0xeZ9C(lQ^J0hJ1pLWhUld5_1FPdA_D2t7Ftq!@ zcLBZ;@X;=~!m<$i$AGT~e0I2Kgz%pOAIFb%@E+u^dMy7=2w#bt!LR~8`i~d917k@D zzlDdvfLFgi`B+El|D=TUOXX!S=F{x6JAWO(cc;dWHi=$V?VCcYLB6(M{d;G_Ro#<8=TznZXNOrhClcmCsnKaOUf72mNB@xKuG^!#C${}%Y>l>g{E zyZ-A5F&Org|L7CD{7t~e{h!30;Gf1p#$N|~%zt7VwnLVL@MpkFZ4=5q+Gf{&2Jp%J zqfU17{~GXZXya#h{Y?^KFbsi@aYx&*9k3*1{Pu8gm`L&ESz|q%pa?^>HL?J{}_L~*v%gW__BuB zM?R}U{PzUD2^GJ-EQl6m-(AH@E5;A??>xQ+hg!f}ixA^b@AauD+ueaGBo zH+~Jkp9FlecN4vTa)R_5EY3VX68~A91HzvUd`HUvKiQ`Uy6!Iz$BpX~dj z9{c=GNWVK2pPjt}^%DL_c<9py`(*E6H~!ufpUgYE{2bsLfqjfU`owPhIfpavpRDr0 z#7`mPpACH6zexN^`=5~TH&c9eatC!2{zKrKfPGSCH-75yB|pv|^6)}GSP^0`0Qh>; z_*u1$`U!t8WuNR{tk|aWA5eVEzrNU)8o^)~f&Z9)$R~cm$KML+_y4y40pLI8AMT&% z6Y=Y}&eQrG0KO^ku|KO^df#W1eT+ZyS)Bu7tH1ll|J(8J@BY)@{X+$Q6obz%xPP&; zhmrWN06yjqu6tJJ4!Zu8D^(Pq+&@_Lf!J3a`RnKdW;<_^!am{g=!iyZlYS$MY}xhdz+| zFqVHO#J;i&gE5oF$9KT22;ry8FrS~%Z&q!ie!_19KKf7MN9wW9?}YSImHp56SM0`b zG4S#E5qWSFWw3e!6Vgvap1FQ7et41k-*K^x^m72dGuS8he^SpXza03cwD_~jAE>|_ zKjt4hLhR@QAMKO-C#yOLKLPldf0%b%aE)bA0pXtqz6tP2>=9WJ!XKdcEB{#KqJF}k z0es9Kj2~X?=I=7#iO#*g^VuKgt7n^69vc6Rv}fo}$UcGf=HA^s~V{hEKQXH^K_3-~1d?5rWe-vE4D z@E_wx>R9oC^lbutTJ=`_Lc7ge0|D))XVPuBMxvp9i>@d+g?4Fz`*me_VSg?D9_lAIFdO*%9LZJBp8GR&Apl!k?td zeE)}BcooOMeVi2``~cwV(B_}r_#Xm3<`40o)iDtJPk@j4Py8nJe;NbnCqL%b{)fJk zdRF-fz{mVUzi|z->wgjO(SNdcvupnq@X7mE+&gKJMRGMjd1w{gw=kg#QKjMwES0_a`p4lfIVf|9O69H-FawALCE-vFm>w z@HHs^as2Gs{|0zr3IJUjZNY zU$jqhkaF?2K>Rm_1E(d$XVrI9O!)m>zv*C~#J?}|Uk!W+!C&_u;@58nPxJph@Qo=x zt6ci{C&1x{#J?~369;^1ph{YL?~d~mTE1JX|mzWgWi z2XvNmknjV5kNYR)USINe7tKEEWH)|oz$fP~^qQyLHxDv?Qipo}B&4rB@cT3V zG|E01H_^+g{dd4Oh4>@CFY%uU$%}jvH&%5JKNka^#E(@jj*ak(flq&a`_s5dJK?_o zK8ZiJvFZci%fo+wi1$A-eo{~D{5K^1Jb`aO;}bpqjYsMUe;3U@`p)VeMEK8X_E{Y} z`at+95Ih_|$v<|_U;e;gSNbFyr>|@-}e|F=?0WV+Z@h5u!n_W^*`b_~o znSZQfHHL(r0DN3O#CLZ6KTq+|FN__#=Pxl>eCA*u{Xs6f{<{I+1o&j$SbdHozIKF&YhJ27|J9e)Y%asLqpu0S97FM&^bl|@i^dP z{4jU$`A-a;U_nUyjsPEyU_aLn`p&NZ4}fn0e2n|ZKJd-p;l~L0Xm=P~tP1fz1^CAO zuwM;)Tz{w!eZVs$D?;qs!Qz_^e9S-i$aefnfQ0eGwaecJ{uoGpa{gd7_rVN<`0oXL zTt8UH>fVig3BLr$CKUfVtI0#-%fihE_aCHU4imlb@wYg=@G*XU8Na>}^Y`<8 z;~#~LU)7kwm<@a+U=E@VR)p}AfRFiy_f7{^h*TfK?*cyN ze_#2UCcl1vjyiD+tO&7R1pK*F{IHJI9435$ssH)=OLpy70N;kPkFjSr{(_J^{o&6A zK3P9~vA-GkIDZ%qN4{PVGC z{|b$d@nhHjQSk6i-+$TVhX8*DE&lB0?@8dh(Z-L@V5|s<|1j(Sw2#k$tO()90w328 zmT?Z)<(~sS?w^FuZv1#4cyR9cD}ULI-yGn((CoA8e=+cJ|3?4uVwcYk$>T)xpWXZ4 zJmACsevTjW7kywwNWa5Ch7|fMe*CPEp%38?o5?&sA&u3&1N##GD&Uj-kJY`4&Tpgf z(LTHRqXU~4{r)S6%2^QN|61VNQSrk%cIWRt@ZkvY^ZhBSu}AlaeGM=UUt#<_KXXC- z5Nu>Y2!A#3@%f(@I2eCcpMePfJn+f+4dc&h4iNq~;KM7}pX0~;WjB5XaCn&re4ze( zcfo275&Ki%<^f00KJ$}+4@a;*^J{>Q`yaU9C;x?E^XQNNj==Aa{cPa(XZ(-)>Hlch zJo@8*DDdGH)aUr0?5BNB*nDvR?(6*90>3~0X9K@q^9TI?#9tL&KJ+JlLxJBP`(?oI zPy9IH@X(+5nFAk=pnabIOyKut{C9!hpYe~L(?9#6!0*rep9lT~h#wa$AThY`9>R){ z{l5!d{jxkI@s0lY?+ScKfj;|R0{s4rUjzp4(GUBPzz^sL zzXkaHiND_b{*8YN@csJX|99Z~^n>pO!N=#PzUFTk@ZlEFXTE@E|MJfl`2Cr`D&WIc zP(Po4aNl6}{K)WPK0omScQh(sQON%D4ET6{M!Tqk-TiC4H*^2P_Z~8Eu`0y=Ye=3* z+W0wGR6zKizQ3Mdk;*Q=9QgSD5%Ui(R)yGCfW?FRKaRgI&rcD+$M~aNq7y&=Nl4$r zG(P&k>KF)L-2d16cdTPK|7?Lz{AblRj*Zw~L-BFmu#VmNs{y_y6+g7kF24u(=D;WZ zaDxt3g!DIp%^#m%k%P8bjRD~=0RA-Kv%^JOgnt_N`27j4Thu}7vCr>>^!o_>>6Crs zv-|uzJ@D83qdnBYiV*wDfo}x%F>V-pQvW9%q+ccQO{wuChu!^)C+OGr$L!1jv2O-w5op6MMS<7lDuaAK|k)1`UjUk!Y;kGw%}u^Ybz;FJ7C9jxX6u`d_<%YI+( zzd^varsBt{ZE*9i{ihuG#uUFV{`XM+qfRmW!=jM!8^`_U{IPrgSPgt~enOq>&fgv2 zPlNH3`@RsH{*PMpYyZXgvzvcjz}KbXkG9$MKO6W)z(?D7vCF>){0YFv^DC>qL)X9Z zM`ZD@^CPRVqw`IHPk;YO&XL&XcS7=KDe(2E_z44n-TbMh@rMAP-S{!$nej)z`w~AR z;N$Zf$v<}eUjlrbKR&Q80~f18;#UlO%zyNMG^=FjNBCL^%zuBqul#SoHv;>pkJZ?t zo5a5566X04sAT zPI4Hg;g3S%ADQ^;{Yzi+?Qu`Ob>A>&L{AB>2od5e0zm|U5mtVm=fA=;15y0<{ z|7Un7=Q;@6Y(Buj-%u z4B+=?{%-*v&kuNZ8jg#IMIrYe%hk+({}lPS{`uJC9|itw%6?z?(rcLCpAi4?48V#I z|6PDT3GCyuV_%*h*8_hZl|NjdV<;=ep%1bD8u)mA#&aL3V?_n&yK^n`{J{?-w9o20 z5W*jo{%ieV>`48ed?5XNfIl7lCvi8dy-Ys-Rt4b~0N)t+=sV6oOJwLr_*xmi{`)87 zvU~nY2R_a}@`z6O_(vgqtARfi_@s=_@T>^w&$sT^e}9NMP{9fr`VhV=@TXAm!!h7G zU_}Uj8}RL@@#FhPR)z3Y*8lqN-{@RVpJ)$_aT6IkWDb1fQ@(bT-iDtEKMwdhU?1mB zfL4!vekX)qmC4*c`pTEy&_8|*@bUStulBD1-?krosg1w>|L6J=zc}Fc$NxIuJNCnW z`Axs_zc2pB0KY%>F9YAYAO4GNX6_%DtC$1BewVbgHj=+HfRFDVu?hL??q6xZHvv9= zchQ&iUrX61e0Kd8-}39^A245&1;N ze`oz?iwP9*LP5m*F{2R9#6R=VfhXmO&w^o8 zIT8@tqbXbfi1CKk-#`1qYs{a5i2V}b!hBi*7sg~QTv!jc+n;4vwm;jm0dd?paG~V< z{L4i2V=r9Tet@b+#Bx4d*j@-1j^_x4M*%SxtKmZX*Wf~-Bl2#*g}izSZvvwH6Qcjk zaH0Qq;X?T*M13uAA>M-v1rd4ou>gXI`X0lDemsQ>`**^Hf{69cumD0w?Drfl#20X( zAY%X5aAEx$xKI$W{ykh+{{b$P-y!z<2p8ffxKI#L&u1)vAmVtwVgUpZ+ke1?Jmw!J zVwvM-NaZ~;N39%m^)lNsO;)g$ogQ#{y)F(id>4^10P>=dVsrG+D%r9}O zosP(tpz0B^-v~gglBVi^hsYmA^+UvuG8D>ED2J6G|Ag2iPqicBM+NwU>rjQNN5qe+ z@CWUwQDt?k1VP05u~fY#RsTEWh5nPMeu(%{mqIpUC~^DT<%hlt~kp~{H(aRF6k1u^dyQT-87Up$3N0I_K)RbGY#5Jc>^91yFL zsd6eH`nQs*Uxkezi0J=1s(w8n@;6ZJh{90b3y9-A2#E7o28jAjP;1rh7d0ivGs zR6Qboya0bt&n3V?fHwgJ03QHi{yhamUKb$l>#qUPK2{C}7z~KKVSw0A68;DQDr12{ z)UOU@d`_JPi25A>(Qgkx9IqcBJ_9ZS#QWnKsyz!3?<+?EQBNr#@-G0Q-D`lD&$j{5 zpLPmg0pfkM2N1{q1rS_kd<8^398ih8L4c@F0ub9J0a1@4ApDP^jDP-y!=P+P)&GAH zF}`+`|Nj>d=YJOE526B;7gJ?A!qhPmpk5v@hiXSe{(h>Ai1T=WDkCEA5LNys#Qu3y zzXGZsD~Ngvss4zl=Lm&IDJ-Je5wZOkAo5D6aw*mRJ49X?)ejLro}kKz*nW~KBclG( zRQ(yM9ufPUrOJrduY#&SPt_yhK37H6S5x)BL)3eT>W7Hy?gmvx#P)isjEHt`QDsDI zZ=lL_#H!m=Jv)e$yANQo5hr>T!QGpxP0! z-V_k^n^8Co5cl7CfGGceK#Z3MH6A+RxIL+QL@awz=naVR38LERh*e?m2d6ZWYX2Q# zzZj|?BHl-msPg|3(f{R?UPLS>1LF8osd_}LUqO`-@jkZ(5c{Q5^#q~n=d-H`egHwl z@t9F)4v6|JD8%Pi6hy4If(!2>|31eu(fIc{7N1{H5OGQV z`yBf-91J~(2ZrX~=UC>x{qJ)u^M3U2bL_v*vA9G0({uK}&$0jcT#NhXzt6FlE%2TT z4zqZF{r5TcXE=U7*Wz=)zt6GEc>G^_{>6ErKfj`fSjP4I?{n;*o@2iYeaArkF9q~* zFqnGjs=1a=Q2(AE-xTwFsArm3MY-p~ivvc^$n3hXB>c(QHhXi&k~`(YP9=539cBzo z(F`svn*DX*!n^TS82P2dFL?!p_Nu2(zk!`*@oYN5P$I*o(NY* zsFG3MlEWKaZ{55$YS%RF#0Z;F3!ctx<%doyq*ZOvB{-+_d&%o7+Mo zIdl%0w=A~XF=4~a%MHx$x|ngGULX8a&2@h4Zca}76lwlst2zb#2gg6mxc%^5Q>#Sx z5-*LSb)nOGP97H;@=fH-tI~B9G3P#uC&rF`=s99m=c!?V4$g*U%MG+s*AN*q;`T&UWzNxD`Y+d~H$R^D)4;ECyX30&PwpX zGdD-s^zpB)BFt3zTWN8?XKo@~W;Y#|%;IXT(pHsMH5tTt$|hyXE63<0oBHyt!9CL_ zuG9HoCAVtWJfd7vCKb;j(?a`{-Bg=XbB# zAGGUkm7SyIcJf_uXv>$f#7nn(%n!exA*1P+Eww~VW~ zKQl{cqMobzt*3gY1IN}kAGNmB%i;-i8o9gbyo`8ftjSTe7sIB!&relqXyiAL#Q&ca zl4tnc2@x){V|G?4;zlmo(&JyxQdu*@>Z|B}S-oA-lb$`&FeprFc;qI&-dLkrE!f5S z*oU?L){BypmS%TEY*V$FXTEa9ZTh;vcc(NfY*@Cq<4Mx?jWfH#TO{1oeyH9| zJsj1jlBKj?II(E>8!Jzbjt~5rPU}~cY?~IMk@!q*;mX-r3%_MM>t0Wz`HSyRiEznW zi@GKj>l*RGnde0e?;gGR<2i2n@ZTD=c*a1t-LI2cpK(S7%gb~hlX@&0@-U;PutVy! z$dE6}sS2z2dLPs`Vt#kV%wK%xM}$kxZA$2}$(0}OhZw)**6SS7*1{vdUUHPBs^^ev zC5yEcCIwpBm@WU|>-&)N%mAqp->t(B>Md});;ne*;N?3E-H$YX@w+i1T;fL76^41i z-Xq7om^&%%rNqdhcD1_n;rf9)olA@OTJra&@^5lG?!GQpcygzU@R=}&)~p8{uNUm# z;iyftb@vpc>BaBnh;Y@d$Q%9Xkxqp5h@`P|zg_U!`Sy-yaEHK=)&%YCcale2KGyj@ zMo8-HF(Hc;=N0BD<#8J=Hh(I$C&Nu^&hFZyocLWi$%mic2~vu=wl@zsFDZK^AdL6Z zNu#XTg%PDQmJJ=bwCd_6_554%qtdf>&E<1=xFcu&3CEM8-iUn_e^9x3yDaB6*{O*$Yi_Z>3xZD?9Dm)o<^zJqlUi-3=qszpE zuP3H8@mXEFH~EvqwkfMdC3|wlZM2`d(EK9jiYD$)lNMfEx?<7NXBFq-$Ea!avkfO);;v6=^aXx0&_|MrXPL|eC6 z`P}x8j{~?qNvyImxgxT0wz&Vfh8Dw{59X||x%r9<7e=@nH9aaY8zy!n zH$U3ye&THR+oNS@dht66B3x^f&l%+ozI(>v)aG)f!XcyP>sn?eCP@$4Z}Ij}!=&vw z7iL*oG)I(P7y3ASfn5;O`oP0zjGnNCH6GDet%fzhyytv6~VKD zio|hY2Q2(t$`3^;3SQrE@#NGe!6QAo%mP}SMB@j(kPMw(7nNB*f9VPL)3?K?uQsFU z9Zr-2awV2tP`MTJead7`*++UNGoCeDY^$!ejvO!N*%6X-sn&dcY^%IupkmOyO>1Ur z^I0esZ5-^n)4#Xzls`zFX_I7U z#O{z&G0`_Rc6u51m`rsp9_+bBC&{tNZspMH_o4@ATncU6?kj86*e>7o`Bc;Pt?#dx zR)5ndjqKcOL(?lw*Bf^5<~gaxU8*6Ra_ymJtB3U3>=>z-FnKEHyq&fh^?qa58T;v- zA5k-Fe)2Qn&~fwMLDt_&U354)u3oXn=%Vp)x?UN&-gN=oi@14X1__3xv=_ZIcv<>9ZNakhwNsMq z^}3fIFTUB(^R{A87T-&AH(k4kOsUbEPC6dc96L`ShTnCIVdvwKG=F93datx)51l)5 zlVX?pHp3V1IPUsL4R8Fmu^@Y?gSgVsEbC<=wPT#NC}?$#EvUL^<1pVyDO7M}_Np&e zFFjmPI2Z`j;&eVfP2#+qlBkB(a@ z;L#fLaqsz&E^lY@+-+N*)UMrod(VWFRQ0J}p6{dSm8a{?6VVuW;eOWml^Ztiji^kx zxIRR?Cz``H!(TAzlm9itb{(b5!+P8KMx@s_M_Af_sW@6YH~!clP1)HNZLjxT&b6oM zRiNvAJ*`o2%$c+YPes(U;?$<9ypTS*cus>??#QPd7K(2)4T@X7So^NKy8pwC;g_Za zY8`y1Ug%-5r)uANySf`wlE>q_f07T1biH05^Us|4UU>SGf?V!<4F$*Bw-Qv!zI&)V zb}W8uC22ljnt_UK;YRbv*M*el?H?VXdsjRC)6}O1N)zqRw9FVhK9Qz(G+l4ep68=V zcX}*;Bot~T_^942`1F0v$k;QoK`9y`F887@xW6d=@NUr^nqFnPUekNFqdup-`?9c1?6MG# zTItl|*SZfr%h-73N5KR~<4Y+|o1c8w-Q{oCxiY&xaKBwpkgucDqa=&N2c7)OXRh9~ zm8MsPuGh@jUe?`Q%8h5k!UKEmK0IeIOfBJMLACmt4DfZj&MRzTV^RRy4h;biFUEI#dohPiqZN8uwvZQPFNW=O3n$Ls#VF zK0M+b=AFK4>|v=BPogh{@pb2W9C8l}RWH|AAz3b$`)$(5!9LQi%{0AZ=z0sb4l#)v znw=0lOlaK9TziN3%KKIOPvuJ{uO8`DHLJ%v^xpTB=dNcJZgjf!DvCN^QB=8i&q-K% z*6|1%kBqjt^!!z$>wTpXx#^kY)OU?7%@2ij7uxl7c5V8SsJimV`o;Qr-BGQtUVOb- z8x+Hx&E;^p!fvsCzW%E`@%H3GTVKI7J2Z$(M|s?+s8m-=ezrtnOn^TmC}*RQkH zOF0wHX7|o5Jw#%YgqpXlKxROWL(5X zk!*pePlM+~H{Ol0@+H;ytuPyago)tU4HW#%7SQd(4^~CxS{P+ z^^E_%j-%&GF9YrP!IklYF1v&#Cajz~aPab3>n?0uyT7Ai^qBUv$)|KbEPOt#YQ=#W zdl^~v0k`TUCoi&~>D8j^jplmA*D>SARpFz-M;9CTUR~_4@mtxb%H;UZjhe+l?VnPE zI`@{G_|bWNUVW3k?cSh4UT16-^(<7m@9(qRdH?22n%;4Ay;A$$`z+C~=GVS-HvXmM z$azg_%}wJv1CIQ7_x0m>^~H?|7et5et2BG0WLX_kW^yB2L!oKYx!3Wdw{zYYI7h-5 ze~U=+L7T4EJ)HN9&`9kr&aT`+mkKmY)WnX(KVN-&q3ejodvlzv=TCU=Ue;tS9a=GB zXl|Q|@trwW&u&ZKGuD-7rdaY&wZnsHddJiC-cR0X`(lWe`>Etsqivvq@YD^AY~Ec)umIo7DHCX6@1eM7I6a>3Fv zWs^aC%J0nf(&?wCT;JCUw;a?QQ9`)>!%N|(BE<5ru9 zo3HVV-nxfgM){NXC=@=~lFryJvg+L11=`7V84}G8bkFmBIX`#q%gB(B^Y>CN7X=E_ z^iHDd^{`9J2pGP#WWy!FwMAPyd4}D*aQXe^OYX<~CLMUJ(|A2pJelF3a>-AbHW*~bn&p3#Gz2DT9mlkn(C!h81j#{

q(5tr#G~5bJ0+Ami|w~x=V~}QcgU5AldV-2C`4Tz74>bi#W)A?b4$7> zb$rXc>7!-LFGkZlnXb2@V4WGimy#9lfy2p%N4pKLxvCg6{6Ln7j`H->m#NP;+5Bj( z;mIAh=(x?jzE-t%lEBCcj;^|?TDi-@E(jjWP@f?cAF^mw@w0R>{*3x5e9vybNiFZp zzAxu+O^EAMbgQ_uWgv(5X zb4tyZRj=NJW$}Al87Qq9F!avzjPDC{9qU!jY8z%L%^PU;V1n;9J%RA2)q~pB3vQ|X zW)uJLoy>#k>3q8tRcLyR{?ZE1L($LA-W#;J_3+UNWz*%_C37drtO;7}@MYQ9FWV#5 zC+IGy+wg%B>2$qg=MC`RKFq>G=gZnd z=Ps`<-ggCz5ZV-?FbKTJz`m~2*T+u1Ssvi|nK z=tBYv=DgErwEZ!A>qLp5r^oVF41X!tJ)5Q%f4@hBEBOAmw;c0~mmXOyQ2$D`+GY5G zg4To6j1}xBJ!#wE*EW;;l6ZSbNL6SNuk6|Q`@$^Q)6$PpEr-Rhy=%+g{_eBf9E}Q$^RU9aDY2oGm|>6;^trOI|fM;MmZ#Uc2(D zv$TA$rRxpT-`4m_zw%aT+D%v0sN6Hj&t|`V(!RGeIAlO;q|&)pA?rTBDR>}nXZlFo z_Hm}?=A;DcPNkXwZa0qyrU%_Tc!Z|cj;?p5aGgS~kmJ;;FY4^4~@BA{fws9p01bc*hCvQ z2iK@qTh1sxP%ZZ=lu4a!uKS+eyU(z9@ew6f4PmIN;K_IUW&vMMC|T z2yp}mR z+eq}}?P;+-5%^+^{OeJ>WCcu*%W}&HSQaacq<{bBNY}eAKBz?}!1K0mL2IC(-m`fh zV-8DuOI5u2%%?KO?s#0>5%;U3!)JKRnD6Xi{p9d|&D&qM9oVlSkp9K9rDfuDU;4S) ziLUq6s~zG}b1xo~S`C={g-Rb&Arryur60T{%yHUQd zOK@Jh%e>61!;a_AE|gHV$$VO~f@gc^(A0t@PxSUTue@1t+?0NvoJH3={?Yz-65dyN z-whkZare6oBl`QPEIZ?C8~F}z%5QES`|ZQtV7ZUM#siMkh+lg?Ym@z;jHvGQvI)gQ zHQw)5H8@G%Cuh_3%8&c%yKI2WQ0F1KCJ_=g{$mb#$;U0b$=@ruD|psSLBSP=mh9bc zqQ2{BmE5K?>Vt1f@98^w{?_AygXWwMIQI4H>+Jd0 z*Qg9~k@!Mc+vBww`xd{p@0)0o(6!m+ZZfnA`2?L5uGk zy56L3cg*&PIxKA0=M^}1eA%?!n~l!q9iJQhaJi7{*UC3hgNkN+%o0ut`FOo^znRA5 z=6$2%>trq_<;yH>e{HaLvLsEfD_w7hsA!^`ykUr8X=$c`7uV{Y!jA7bW;Io=xCvaWYO?_I@9lddjZKKFX!Q{xNb z1sqGlzqst$dUDs}c|v{(tF5B;9jfkHIpNvWv@0~d?nEgd*Pd4K9noi&@OUS#7-{fw z{fIjgW(!TpYQNicac`V-#Nt}#<_ey-B6)^ zi>4R;&6~f3OKn_~fgP9d`z2R0v_FN97ik^mc20#cB6Uv2<0q-op8T_0z9k=hrf@W? z`=!H*>eKm-T^|-{oy_5n50ttt%lKMM(>wn!t>AB+)eAQ@jR=zvMuYgKX4leFi@77; zpOZ*gvtp_m_u&h|&E@Lb1MU}mKE79IpXbBXTSs?Xxte5UuVk`frh8-aMJJkG54zr) zqK+SAGR}Hw%M5c7-#gRI_vC_ui(Ts9hbI|aX**_BTYW#W=k+kf!$+oXJ?P|Q{MNv0 z`jhlGLJW=<Tg z_&>IKbamF&Z@gbMP&R-+>-%npl3`~jtuz;T7jRkYO_@1OuNPhK)Y^6NJ==PxMah1~& z)xiHIl$=w&>3W4<_vX89shMlBPxVT+(uC}|?)w9>I(3Y9SMa8--4Gy?_`-H&qsdgQ zgPd1a4%4ZUh&OQaKk`FeOZc5cT4>RWD4Jd$y54U(KNM?fZ@c+TP~zTw)>@}UspQrK ze|bkiRpW2En%=V`1y5dVFG;`jExy8Sd+4MQt=SjMb4zD#d+~T$RnFia&NRKgbiLBt zFIp}XZqzVR(mETl-Rq-OEl=x(p-NU~(s$Vfw&FJPfLtBeL1zwzRY6{ zR|rQ;+a0SHW=F`_(FkNqOiQwAYAB;)DE#?LK8^eZ~ueXiVauy$ZWXJWTr@12n zZ0=5eVQ<&F{d(oGpj@%JcKdE#&rVn8$y>T-)PR?kejjN5hS2pcTD7D?bL_s=jc&UL%Wmim~-39np_s8h3!bc`k^Uqoph;0;~p`CyoPQeo8Ei+%A&ds zC+P1HL+N^>$5p*uFL=AvL*a_g2#5NhtHG^d!Y z$qA04mS>ewkJ7%i`4x}#UUh#?Mo2|sPl@(3qw}WB2H0l+nMR52x!*&HAon zW8CaC+jiik*u%4H)}DO6t99@sYloagkz+dE4&BK~^JA=ch|n zrso~{krDFRcFPYMeR8Wy!#i}Q{8 zm-3LY1D%Bn4$G_=v(oPAeuK+L5^aVL*{8YTqRJstn%+pd-V@Dg92vW87QcFFGC82Y zHGkmRFe9EcX;rRQ1_qfKnaLdzozkI2mCA-CJU%@qCSLyP_+k3YppRV7*P34&y*hLc zO>Y!kZ^JE<;{3wHy<#CxsvnN!6Eh6CedqY&!~-jTXwNQ>%Xz=;si{)MrP`i^_H%3X z7pA@baWtgt`ln$nY7(xn$DC3KekR0 z_e{GmokvrR=I;W!UW52i+~OKHg-r~F2JAAPGFwOL#eq*Ta*eYOmX8Sf+P1>%p?*q^ z`nX~dw;O?4l_zeVOa5V~#Wz(-;;4BFZ=MbpP47awUd0(NVxzC6d+0dIrd;pP7m2?h zFqi9~bk>_Myyv(xOJa>?uOI2u>fgxtdP7mKcZ;c8^y-i?8e=)V*2y>@8amXGrZ<+Z z_cHhG#8=lXHcf3_EvGT3^Gnf#E`fOAtXgv`>71*zv2V9Twzi!%R93HC7rmzXWLB@Z zVY0w0naRBoQMOU>wGs69Msak#p63rOj#;60MAB13efA_BCH4CuBR(Epq$wo%WMS%K zBkA!GbszkMjOK)wtiJbR@YchtzSy4GW1zCtXn>ba{ssGgBAoi+YN$>NKqQ+jT9`}tJ}oSQMe z?V?qCG{3&C<%jb}bat-w@pa^Ou6A1!v6H4Zp04*~V|w|U71y6=WgjczIpF=y(O;$07R&YW&4<_V*c0e>?J8Lk_blh?qt~bfer(LKzVV+PO6bgL zjgCte7Fk2lLH=rR%DHiMg;Q3^pXBt-6xG-#;nctCS1HJHbyrCW;Ccbw4;4Sa<`DN~ zr^14Nn?CW;Z+>9$WWjxdJCs6IB*lV8TU@rZO&+Ah<5}s68nO!xnY|_XPVg|T84R!_4RJ+6L<- zcdp%@lXWtZN6$KzwZ0*ItVGtgr7Hl}2k2&a6xM+&v_B7*2v8h*&Tjs)M}(}R1N-{O zAd`-gDl@vYmgZAQ^0wmngK!(VHCw?+##nX}EPl0#!gO)ha`nr*ZLj6)3v|y)rqCea zw0zyGd!_^!i6$nrMWA(T!9@!&TQ!oXNZ)TiJ9Z<#k%J3U$3@}f8IT`NV1*@GXPvylq&Fbvt~Q6Fih#|H4a19}C>-_8aw*KF9*F!%J2iYJ*%i{~f13U#-? z%wxiTGLHhsix8m8u@&*5Bt16!mOMLAgvC5Y4sM9$5*8^L2lux4Y(7kbWsHNKE z&F{tSIuf;g*P<_fj>{|1>~KpGDxIsY=|jY@9oap)qaYb{Xo2r?Stt@Mlr5K>p_y)S zrXnmk(*|(Efvz8}gJ%}efnh}e+>eR0(1W4VO5WBV#1EY-E@A>v+8A_Akg1=Y&XRw2 z^13@gL#~vMf^CwJc!tcMPt%KnI)UvW0_Yy9TrS;aWsc|L&RhJ&0zBh}4f^9Id@O=Gs2lu`NvSvMS~8JIcYkC#W=w{D zrm)6iE{j0?pMED2==yI|ozGLAV%p?SuQnrTESIsNQXLfX7o=hmdUj$gN4mb-Sjwkv zIjsAzFm6k<4~`&2`N>m+|JZton@<&6W)M)mQ9#$Y9o1l;JDWGPe>L+|pU zhI%Yo_=?00Pw^775_KYn)|{w(|7*h>4x!H$^C+?Nu7a)<@Ge8FcJYyBdN^#?yjcOiC8 zM~OHJnSwgmMLRw^!Pv+bX=zZwFK0cQ-9P;r;msay4(}wC?piw04W1SiARU{;0l0BM zSE&{ZL|A7n)dhx!8^6&DlA7tbI#9m+DjS!cR0ro#&lHSX8N#UFHQ}dBo9WuKgpJJg z4NgWY??~FKa+3$15#YuHU4c!T>73=EZNt#|p!f8rRQg!1KjiK8^pA6%x)B4A!#?^D zT>kf=pXGSYGP>(wtcb@&0uP)IdNMu^2qaUNLxKP|0q7$5H;wo$lfUcjyA(sz=)bD0 zb@e_hKSE0CYp_|OLTmB*Honr|msN-DB3(gUS)8J0-~O2F4dkzoBwwBvHIbL{an)9U)}(9a08 zN03G?Q-W4`fP9mIZt6_mLyA4~(srkZO>Y6#{Flro zy~2elPx>Lc<`mt@AIHSlnP+e5iUyW=V9}<(m4I9`N0#(m5m{o-FFx_9DgfLcKvyj@ zYY^>EL{+%FFOiLjJ`%UFVWpa)ubCBb-gyhdK_@)1B`p2hC+@gsA1+>&yj^((fzKJU zbEDqJHL~LxD8T!DDL}V+66^;N`xyh=F}!6?XcN3Tvl;#P8xIBM6^CA82k}4cD$a_i z(5~?*J71FmPyz^-$yYYdn3zZh zdCtsE8$OUzAv8c(MA>@6KV4$!EuPtsK?<|SjP3B&bVv+y!;9+N*@O(s5a6Z(-4B`V zjo`V9opB*JHDK7BE)C4>-``|=RtD;HS;4~{YE=6M_4j0uPX^wOSPv;kie0>cPH1Xz zX8E&0#{mZ4Edy}Vf$lGd$PK&n$HsLive0^$)ZOIFNP-jMbG4iFE%ST+Fp%?Rp(`21 zfFj?UK^^Thjt+eDPeY(yPD6{Y{fe#?AmF`~pFkHou5Le=UD9*j?+Z_W%kn7>Mjg0h z!3Q~r;z4m;Bn#6YGD;sW&b`pp$l~7)1g%Fco%8k4|Kb+Rlimz7%V+EY9aH3? zwL1`aGQ#tTbQsFw4=x=EXhRwouSF}Py0={R7g&GvEJ4|vbGO+xX>e4H6T?B2 zgsQFeKH-mG0Jxbzcd3SMy3%j?Yu;%=h z#qu^Ofy8AwKrGOk%j8xv3SBRsozLnXIFHH#y2Hqe0o7+NxH2M23&@wz8PFpEvF&)l^^pD5M#OyS-PDuKg?G%E|A&T zEX4JsMr}Ts^fF_?h3P3;ikh||Bdh_>8FGOx|IoyVJiakU?(QWE2Pv7GaIKCsj)G+N z9i`m$6)FGB`h39==71QKW1}vv=o$$osL3F)Ze)pkm*K76f)XFFU;hPk=hO1y#9cbS z@=r9>%2}t{kYW!c3nN}JRaMX6f0!C_L5WKr?!8wT$qHK@@`>6HjIG}D5GX5nhU&C@ zc$Opp-j~Y*x*M6@?lbL_Hkdm3ClS1_fErAJGx!m}0w+ybEMD_pIrvcE-Y zsGoNHk%hlcNGyJEm2E)P%{gRG6`ks4w`5>|F4C(896H27E=>uM3>m5ynb+rbwCu~7 zwVEaHT(1!5CPR#%a#`l6IvJoz`fA>w^Yi%CFn`lAiL8OIAce5CnIiL2JDHN%dH3kt zN0x1S1P-c)Fl}4!uOWgbrz&7)0_0l+bc2r_%LfcD^>LHm+-JhmY*#iLM(1L@+xjU5 zfyeaaciYE_<9@XUZ*!tESXnnGX=<1K-rtIfq=$59^L~Z&KUM&4G0U zYm>*y(Mu;6q}3Rwy*eO#df@-|-Kq$_vDunY;Vsk#Q_ysC72WX-WtvAU48D92T#v<#!C$Qm-FwL9LO%^OiE88%;Zeaa_gKh1gg( zTCg?)iFb(+jvd*zAGt;L{ukH&A4D6bQhWa74~fBpi%YYGIcwi&<>q;XR6Jrkt$*`F z1J|+TKsV11Du)$2*}a9SgQN<~4Y@9kSBh30DN*Qcc5}hRcYb=PjW7n{^Utt%g(4IN z#KIw(hIwboWa6+T3CKf=u)zBo6+rjwO%PO68I8Sx!Px!+ErXZ=tvswbr^$o1@K}76 zU9Q<5BlGoo5tr(0gmU42MNM{E?_*QFs$7_}ELxcE+fsBuy;TBTU;9wGc&5B&*id>t zZ#P_y5L-Rp%tF8Zo?r1G3al`~Ci_KxyHA{7A|3a1WI<=yAFP~^V1=jV)NseI>df4x z0B#k~%}KzYYzxUG$%Mj>kihg6M|7?uU+A0IP9y+vZCDz$@Q!Dx@pQoYfHw>)Z2Tzv z&eDadeIHsV6kkKiby=dY2XL!_Zl(YaJhUX-LXJ|fxsL+s0qo`**{ef2f&||?mp8+C zlqHUBQ_3RB{?l={ts-7Q>OQ2GKA+K3t_?hnukx609RO|(&|L^>=(pz}To0`cp()!R za_$4q(XAg2*Mjs`Efeus1gUDkkvuS;TS!4{6n^78F|==+hb5bXUQhA(!80!EZVhm2 zfo>{F@&QS$D)->*Twqjqoqa_kagshrenh|TcB^5=_3pOIZe+C9+WmGRR$)hV2F$bX z!%^s6=ueDvdcffgd9nfXfii+xUFNSEXWV)c6wJteY>pprOLcqlyCWocU&L;yX`cO4y7kP`7zXeTqhZjZ!^$s zwSYuD`Wm;5-k|13vaT#ZKQ<8j1}iOT^6(g4gVyJZY{_qaI+bpGZPkdbkxJcxfErco zZ9$4>OfxOp$nUnmeYqB(>l#ueq;IWMreT*`t7?5u((2Z9r^4`UEs+^pZjG%V|2Jnx9?>EPHMa4L&2N6tUb;hdqRNQ26TDc zdMKGtsPkh-)Q{0caXMv`-W7s9Q>2HP7r4k$H;-Av9@>V4y9>6YFV;Vs6U8v%a-Whc zk7f;CZltje`lJBdcA%@LQ8Sf6@!Mn%WegeD@vc#H^#~D1I?(jz;;(>4et55fTksf$ z<T0+g^0e}KS;y@+zy~S((1zLn;vtZ6T@Vs zq<9)XdM)ER>K5IBy~24bQ_F}{Iq%Gu$MKu{?hE#~o_jw_?+deV(~x!GbI}QO=dWfI z6lQ%hh**uab=uHpA0V}!*#tp`H)pwo44-E6Y-rANaC?IdVeVZ*B*7+KYpR>w<44w7 zH0zt^S9j=u=a9dFuFT+9_vuvzSy#7T2(?FZhxDPC_31J}UfNOXRPuy30eJ5`$R|cN zNPP?qSe_?nzcCo#Srb6DA9j;J4~3Fa@&d}C3+Q^FPT=+m;7~q&r*a*K4n&>YaWf~3 zY{3!pIOv$ot8XCr6)i%C;Di@uJ~r=l4clxD9^BRoWL4{qPz7 z2yVLr3BN^n`q?|WR&*HRx`KqrLRe$RlFf|Q^FQogGY+rDkAV@^94I{v+Je_glV*HS{k?*^IW>9)op+^lv*Tnsm) z><3L+$N=Tg4|LtTR1k%jC+>q$SlL+lmI%2z11_J2?R*g^gEJF9+NwaS4A078#Oocf z&S-BMK?QKP+}QfR!9gT0GU{`&E&|Rc2Y{{=dxbG-A74W`-oawj_Rg8&TA6r=rWO8z z({7H>M>Tv$Yq^Gp+uIs3V;jM66Ll>GIb9hNjuZi;UcVc&{jw-PzJowlZQwpiE#b$W zH6APW5#79a=l!TTt=5DPn{4cmS>0b7*5^qDV+mDi=Lw=0$$f<8&OUumK9)3c zgJ5~e&gTlNc$x`%EStmn`F(w`0^kk<-ADVxfYjxTVTmzij_@kKheaPzztFW(V~^dO z^+V=aF6sTZHsD>NT06>d9QhDtSzL8&Va^c+*tBz#Pp-XXz;S2<=#GxyLvH2jd|(+# zc&lXFe$SS@jEw?5kkH8QC31G`%1>1@R0th2VSKQ3Orkj_ZROQ=rIh4KOSOvsj{i!* zOB;~yDA0vSPiGH@m-Y4d#T|d^TthH{YK{Ec)q-@sDBCQ%1XY(r`i|W?nyaEiE5`e( zwCf0I-A7&EkQ6_JtI;N3zTOPrjse|YET3j9MJ+Ok3pmcRX-gjt^2sCH`3i?KZd;sc ze%!PVeB!M+Zmo{3Zy-~L_SV&{5Ozy03=FMPH!|>h9%xbmxZ^;VSV+)*@RE`w#p}Wd zChZHqYFRg@FBzf0N|Ew`q!8Yk%$?C!`l%KeR~);zUIy!{t|C09-i3L3JmO^Y+h^kt zfI9(nzrxRmvbE(wZAR-BKi*<~93_71C3!;)pMX>uE<<*nt;Ab|UFvQDg-f-crkNj@ z-Z8h3?XbQ#4>fG&)-`2O4R9xct`G+U;y&7#mJQy7EeoOVH>Hr33PT6Ma0U3RSlOq@ zL4I)+i%#Z87mwC9eGO)@l3kdC?5u89| zrNWcS_MyJkej}sJe|G?IXMk>j2t*gzm$k=I9LbMJk&`2seVleTl{C?jv@w|czK71# z%9?_b7ltn5Y&86;0$#ThuHQU@1C2(U8o<;iEd-$e?kv!ap>C84lK(Yw5+9Vpoj@Vw z6jD|)I4Y;+*M*0HT*Bk+QJLU405y!(AaL@TuSaV7mdi+jC+Arg!-#JpZsR%>;LZWv zLkADLOa9)7D3_`h46>ZOF%61RoRWJc*IVpjU-mvQEzd=6Oqw~KcW6P!O2_;YIh#4+ z%bzKuiCI;H89i>o0q#7|#aw5vs*}63P%z&t%9ejuG0Q)ab5$HMz zXmU9bq>n3AVh{2^U#JyD3q9!~B89=rDRtVCeX@FJCyk%0(24W#@rzR-3VM5=vq=ya zL$Waf_dLlKUT_L?g?90NYL8iRA|!ARU} zzmqjfr`Oe1^x;sBJgp0Tp>ZE7zHo1Zb3H0YKfy|I&eG22ZPOK5R@@-~pNnOnYwBYR z!h0Nk7T4IjZwo$l!ZQuBV)^_DUJJ>0hn7I&Piud%2<@$FYy)D9*(L2U z+5D$Bt-`Gj;I0GRxv^zA@2sbkMN9qcV;dy1=nGWM{iW40j`mhtcLlOCj(}uUI7Sbv zGR!;dY9gmjH22Bfruva58RBn`>sL+e0CxlEmPq`WkK3)jC5yFJT~GT6ix<9g1%Jo>FTdjZ@{pvxlc+lj3% zhj0h03D@H$+~L84Rp7k8mDGQHG+TeAR>p#1^j;07SJ8F$2}z!JweVg<=MiZYo!b~uy(JN)oa$F?xu7om7CopmT5IW-rW_) zZef_U-XqXijJ@9CEbpzP%`-OgTmas4+y=S?pV6J{-!>dn_7o4IOBb*2gO~#vGQ)yC zj>Vb`FMYXuN8HoVT-wGG>aX>9lJdc%g!CO$F)Bg7u%UCu$5^aHKsoFHT?4A$?r*mP zgx-`L#tm~?8+hNqU63{x@W*3W>ct)4@jrhiM;!jxHL3X91~kH1(KFkY;{}o-=_b$T zpr&T~GYfEcf$lYux<4O0@7~t6QH+c%T7Ua>d3aAbSr5mRz57 zSa(H2TKpiHv&><{a8559qD^;Z=b$t*oj;62mzH0f<+$6+5AqP1GqPE9)agbu$)P5^ z=OSHg0qz0N{b%edEsM-rMER(%zKE!Mb zpQXOTsp|yC9WOpABRUll&`NdQAAoxZbj_ND56b;+y=Su=r_MDsl|~4c;1jZ5^p>C@VR$->0l#qzbT9dt8XSxbxzXM*Xv&<%PV6Sftz1C`zStNVf8nZ2r3IKt-=%PS{2V}sNZs_ z*ZcQo?<;!Rgf=IJRG9gH;eRy`{(TCd1-r#3UaAfxMBH<-%? zl*1*^Rqr=^dzqX)ESET%AkVH~w8~z@QNPT=&y0k1?CI7T)HPDL_lBIFl&?^M|Glw< zonNa!cz!sU%f<0ZtJ&Qm@E-IP&{f_<5>uqP{k<(3m{&1wdjX!RZr@;Zu%NnJJ$L9H zfh4#z#LOt$8)$zNB8Q<~YL}@T_3L}OL^`6@DUlPb-Fra3*FaaSg_|@88e73MB0nn^ zvx)JNvMK7R?)*?r#8xjU$@iDmryI!?@fBi2Ln5cX(^`SBF%+x|gB4zoBAV;A{>~`C zy#cz0B{@yU5+bB0Zja_E#X9D8LHSP7gEvZQTtysA$#V(J17`PiQCFd(hut5JceLB6 z=pd)F$y^n-^sWh7b+&=~8n-}~XiLw`b)@M}j&8Ivi1yc8$T6w2CZ_jjpB079Q_M)> z;CYaB(*vv3ma95Fp<>pqt=SkDNx3q*LNHydJSy z-8C3-NWY#^e2#9_Qvi1XZ$vjRCrb(U)1f}Oi?J~@g?&STq?ILN&|_&s0{W*?8L%Ag zf$s6>@x7}bW?jo%-ufXmOAbj;ppLeU#^rm{(t<{)qqJOW>B||MPdUGk%k(>BaXX}# zLBt1Fu8*?K8*z+ZE+7E;J^1Kh0)sI_X=N{h+ALa}*-FyQ)KYj$dOMz?CqYQ13kCjrFiija= zo*zf8xvY|?75u6mEBILOD3F`cHnXR#?R`2?_uW*Uw1Pmv`MIqs8C1{7!!#+TWl12 zpppr99yXig?j**v6zwAYcdn$+tb4z12^yQ4=<>SMwZq4*k+;m0`FF~(l8j?2xjuz| z@5_O~djAK41KnyEuc__6M%IqKvVb<}f$HAY-(%XcNt8)n`A*az-3{KiJqyRGdYrk3 zma<5xoD(~8tq<1eD3fBY+@pZqocy~N1Pk`!zO;?k0DUm&!c+*Gdn?PFV|9ZfobX1^ zgtpUn{Q1H5;0GAqR)Ex_$kD82b5-DXZ;eC@rNU&y@m|>Rq7Qmw??a}a3HATh8|beK z33SaQk!1hes$K5&muy$)IgdbR*t5y`79N3jLn^hFaz8T=pes?MS1A9fj(#JItlqp4 z8c9tCPuM6V*JmdERq*7m3kECrU!owOyT3!4sHry~D4`s?n>)u4G*Z&(`m5xI?shU# z$Pua4Iol?5sl$CjMf|3~fl;U%voMb}hHN_{UB}qgZws@aQLE!sWDMZ0zf004Ja-PBl zHq{-00rE%ope~28i>KZ;^F=z)NRV!-Wz9LH|95W%3>M`-@a4|JYk;O}@a0lUCtND* zbUdN)_J<&Z9rwMtrwj1eLyXBwLs|T0|EM>L9;z@3+^f%P{zASY68^ZGm5c*(9VBtC zZ~yWeo&WtoytuGHcX*$x5^oO_b?xeI*TU-52Z!nwh3JRM7Y`XfpShjfN)q*ZH&Aj# z_fSGYR%%5_{|w(4MX)W86I*zCU);`R@}K+ncN*brkJYjPdt15=-pWAWi*y24+xmo2B)?&c z0Nz+RWDRjAJ!c162ju$(=o04*Cmx5A71!GEe{ocafE{3+g1kh^;{FUV+3Hj+f>0hq z^3Jtq-qV3=JKYOj3jiApm7>DN1A@VpR zeOf1M>mHcfcT1&gDXO%2P7s8Be==f=8FG>R7;=(4bRZIcizHu%ZGo~m8o8z*_1A^{ zTMmdo*YIWrDRV6EWOHs|>^%oXGTu$mbsTlrZq8{UHL18Wg)yY8<9dO#7MT=P#C%WB z0)=nAP?J`isBv5AphkrIzwcUt{<=s&H>9HU2L&rlo337uJ831%BP-!Y_I6BXt+g!f zO2)?GLo7Xt7Fu*C=gab{D{c~(>>VhpPtd;9Ht8%WMH+Jb!8v3+4z$Qh3H!rYrKMObT>{^++!+&igt zRQKXtc7I(kSlIsx76s^1{xN35x*QfC)E%25wAF&Hi|U8OEC^8Gf(EObEn`WP!e`Eq(! zU745UN{fUpte&xnd1^yrVBmGd8vUF9g8u&A#LHcX*8m~IC*-G;#6*#3m|ZKLt%5Qb`pA^=o@%u*{#OeB{reW^ewI$SRKS2jT9RSPDm=jNHQZ_Iv6eW^dt<^y z93pVQCovfhFIR$F}Msjlv{)usvvg{s~1=URn?Z7EVuN69Az&*>ng!Y*j_*$I-}iv`0rhH z-a&>9b<|;u9Q(i^e2z;Oifa{cm%r}6`NPW{?$-dNbl}rC&v|iOs`c@Uua_o746}2n z|Ad@W#==vUR?iImxfvftE*oU-|V1A;uh~L@nIw671(h?u^zNzD*C(7cG?eR4t5t>{w#C$5xsJyM% z;clAIkSJ_qMH>CLj{P@o;sIT0ahiLS|GwmTx3?3{ft6LRkK=KD=CqWs*>dkvzASDw zP>zvrL-Z~Lb!vy1dL;LooZo>j(~E|$1mS-ehtv~m<7FaIevV` z00t}4ZN-yjEoCz_o-zF%NZ!&Wm_e)5p^GeflmKu69&7@Ys~*z%y3d>r@&*cx9Nt<9 zJ{sfyS^xe09gknm_+A4f(Zgi4h?fE{`|xvCgZais?=1JBxi1bTuEN$MFF}%km+Y|r z7brh`wSXsh8%MZPO4h)agG{#Sa2M&Q>H5L#pZmA}eYvyn8lXP=JKD_jJd^p~Zil6t zR0C@k9IE7`-+ZXG^HR){ky~g#U7KN!s<1JZs&53>5xND4Kucjssh2tz=_w$dH>Cb` z|Bc5lZSFNdx3>AulZZ&orRe&Y%2L4tQc>tFqNf-q@~|}02K8_l?9&f>!n|RneUJQ-Bb!a z`yYa-kYlDMWQqvbg+^IIz2Eo7sK|3w-<|bT@F8Gk6SMWQc_8H~?32JrDHmd#PMkOR zc)Wf3f_KocBJkJ!H@>~hv0no;Y`!3sXc3pB*_f*wgXw%TL605)ug);Jnj^+yu;_gx ztk}eU7;`5`#nO$}Z6SYxp|0#nLmE-hz5Gah;Uf5No%PQp1G+X-`Xp^x^*&Nc+|>L5 znMnD0ijI&W*4``hgEgOAo4|69Pk;6AS>}0yJonRp9>D8X(F$#%|}UYu#~|b z$Fi}(X#TfWir%Zhll%1cjGoH*Wek2P-xv4gj{IwY1jLw$_WIdSm4$L9ey`q0;QB); z{6s-gk(qKc;y=Fx-&RQbL+@qjvhBt0hqSyo$76<aJbIq@_&yk$L># zZe6Eu9T_e(bq3qp`s@B1FQ|Yni($0KPY-ObN?l$5bAGa)d(T~RwP0N)F6B7;VfPZE zP>)IGEW@^Td{zXI+$$zC(&}{PKZ5f2kX4W$!VLUmSh5Z$?KrLPzKf;?mv| zn5Gz5{RxX>>|MJ+E+eb%ha{!BM>xMR+(g9(^=(d^G05|Md};l0r}DcU8w1uf!(iFh{M=60g=QKnj*IhD-Mw=8_N#s{lz#vbW1VI&*W4! zjm{%epj>CAh>nuD_qouqZ<-FMiqvTC{yoS4@_nhp*8th#{!tHbZ;i)YbB2=T+vlUg z2JHz)bM{X#P^qeZXbbaG!H_|88|ibDz8)djEb#a-z1=HBs&QMdDQH@KJ>U+=ml5dB z+=Hzy(hj1qxJseyg=_jdN}|d?|&ocXe^2f@(iJ{wL^ z&8%qFr)Z3RAC`kq)8mD0Lngxs-Pvsc~5W8F=!XRYu)kr(a*)=6T zHC^zT#+yx7Xqu)1&z)F-E@-I+CLx)rgHK_=sL0IKFTq#;PMDXSWmHMsIt)iXWwx7H z&Ox+(i3}3mP3^npyKJW^TRTgGcEnX)ob4#rf9s2X?ST#G>Z-?PjM%i9>_u2%T8Pd; zSPj~#xt^z^Kw2L6sM2nu;f1~J6*zvAqOc;Kq_Qksv^P`mMT_k1eT&5r{P9E{@I2t< zjPEr-EfSFYRT^0;*!1(Bn>%K>z6tFG!iK^x`%M}*r;`-{@|D6w%J*`aRzwn!h- zbk$264tQu1&gL!n_sCG_=bM%@N^b>GeS%QddemiVEl^(iu-Ep$33L(2k9LAq^ZV!y zIi!s2Pk*^L6eND!B+*E&4o9j;LB;r{V~o%8mX8E^#IWhC^FHT_HMk!iab<|!ioqab zme(2JzU(o-2I!~Xd30ZlU*up3RkFTOOQu+-eA8k211H)K+vgoL;t7134)gIN2oFCo zvWJ#clJGj3z)maX6y#XZUe4O?R^WYQE}+Y0Byze_t2QBgMKHB5mG0#jmr=fd{l`}x zmbt!;MaYNR&(<+$+|lO1A9muyS8S*sKaf7Xcg59l6Z2;O+$|#w$d?=FQZ~5#!7zm2 zWoKh%>QrqE^L&CKq2)5F*8zbIrA~2mT<|Xb=t$U7KX=?_790WbDbo4ddloN=w9v*E zKtTorpEn+$8%!IC$E;uEbWdpcoAk;47az|Mar=bmZUcNqQkZIDXT!E01^kB0&n>99 zG4KRQ_VdQ{EKW@Vs8D+!t$oeFU_idSK=+a6cy)oP4^qf8Sp1iO`EKAfF5h^u;2y}+ zQf^0Fq9&t8ZI;H#zSFb=fOlXAATC8tp7gIU?Ny7CNQhC z2Rmul>I41-}O9?H?krcTauo-iZYar|X1OwE0prw{du%yaN56t{v_83O@S` zOjKsU?FX^6qGoyLG5_+VVsd;C^x;y?l80jax6k#@ed*(014LmmXja6~#1$57Pm!>g zJ)G5$0Irqs2#xDYW@qZpKKdPjD_qU>>}Xh`EEoo^reFdwy!S?=KvG!=R6{Qt`Ld>X zeJ%unZeW`-yHu16FPY{HzJ5gJM6N)pplI0`Bw60{7pgbSJ1l2{M`WO;dTfhm36x*N zn2h3HxlCspcBU+B!j$GTcK}xi=pK)Z=LU5U_4@Z-?{p%wAayFH9iAe z5uh7XT{~w)ETWEmg&1p9z0d9&e%Oq!IVo3g7v)o632O zZ{%X3nToq|x{(AF(Uda46$QHVSw_`wW1%8j1_{j2&+Y6B5c*XjV>VihKMPIqE?ITR zq%)-Uy9wg_nR%M?5(=%A3G&}_m&lFZnJuqKF0X%S1F!Wa26Scpl2e9Ga3RIZW4_p{ z%<{sYtfw)jy4)6+1Wc7vfe-WB%kLzV#|1UuyWQ+gDocD>U0lqSu~WC{l2iX&81iDh zy5c~$Sc9&mZwPMOD-$(k9}BsY)ZGo!x4SotwXeKR{_x2tE-#^sf4w@HWLL(KL>$x) zTU*ZPM*ya(>AS!~V5Bhza3z4Qj^kt-?OJ(>xkabA=(Cdh!bi|3LfD3U8>*>|nkZ)F z*GlkNA%<3yTb>Vi%q#pxi^NwmYKUU}>NSZ+4 zJoN+6&3Y>l<>-Zya0NTHt%V`2mH+b~#TQNjdXz^L$MDKwifZy)In+a5iQ2RDxvn&Z zS`Dn#)5G}N;MZiflJJ6H;QZlb5A-!atJSVh7hjTpjmjjosQ-}Xn|U(*kr5m=Q3vMg z*N0d9IVp$jSp?y&n7%{1hxu?z4%+&XmAjpJlIev_E~zEqOOCJg_R`0{21u`mhN)uh zYef;e;J7nq#EBaGRXP0%kK4gM^aHDSs{c3wYF(WI90vBJ8@cBoxnL`}!*(Vq>jKR7 z$0>73*&cxVvd8fnATPJ5D}RCRaYwb6QKZW7sR}gml*`T4faG7|@q-ps0 z@P{Sz7a#2m`R}nU5J-p+^NQ7mIKkQ6R{^dp(EYB3m+$)iJ&oHbh2s}V5cS7~=iaPk zS$HVpzCw@4$7uo$wldlXwLV_W*d<+YeJ-;pjECw+arq1Sp-0J^No-0+G1yVpCR5J(z+%?hj!GF?np zQa={7^zP+hy*WtXJ4@kL4%gW5Og~}u5SATtNp&s{jpi)ZLcEBZ`q_>+Hjn?kp~1jxZ5=R zN|X!Qzxmw=aFu{=NvYLMjDeRhL?Dld9<~W(-TUc4<4tPyn$$Oh2;Q4LSsk9oG=}+W zG5cY;AeZ|qKDqj`Hv~S_ha}Wn2nsVk0QaTOd<{@_zj$xtXB)bSi}yMnPW{+A5sNZySScNYY5%w)5+Ae@8N=|2up0(ISQxim^JbSg@u6Z)g#QoRB0 z%U#OX0HHPi`h0pXUWsXpDvUu*8oL2Pcgii$VzSe zx~^-zd#}E!cPrS;n{) zt0k)940Df=YEL7JZVl!^np*!9{vB1*zeUWb`Z7aqn_5k*`mX66z|{k~T{Rtq3Bm?) z$|tp;K-`Q22lo@FBQ3Wg(l2a-TVm8#qWJx4!A=5{cpLk+LM7clo{UKF-xyv)BHs^l ziC)*fJY%o*rVn)EF}>RK!eW+TO#M4*R4vWF>IKEkhO&@;QeBK`#8FyEP9-{{8#E)p zNI+rvM2K>q{M#K_+BZ4hxPvL~9QT9};2Hp3XZ=7E{Jg`9hI0L{2)5Ujf3&c&S@7B* z%;MwEGP0wysg(j%cjz$>u6YsyWto!**)VTZjdU+$jl_E{aCN!S0j?p?{j@Kr!&mi( z&LDrMxqG?byI-kMpBo*xq!VAP&d3<=OswkNcT5Gl2(l@HblgbnUj<`Ill$%gbX&T@f1KkzO^_c`!@_Cje%(>)Gyt`=CmI-|XWD&0AOj&@IR+;Iv%F z0Yay?J@eg~Cra*CE=;%(Xqm&1oGpG&!h(V<|_qKTC`t)e^^;gvCHSj*{&z^kINh7uy5hecoR&Erh^|&u?W! zTtcqPDz|GXj3n=yJAB6i>~~(qy4L_ILD5#I@+#v887V4SAEVI8&G8A8PlsDdL zFnL0$Z5iuk(#8AVn%n^sZGKw$2I`2H!Xp#K${Un*Rcs>91%P0 z%tr}0aK__6^!*x)u;>pMQ^9%7wOehb5uW^ogfb1cR$H`ZY$DpV1l(N^qf6OG=#6wQ z|M%Da!3yYR*V@*j_dwUqRyGhsA#QdH+k7Qts$G`5?Xv~-&%?ctT zmO&r%`py^546~w~D;tc}UQt#Ja9{R%UIXO8Ynw`MB|1=hlQ`4%y(;piPE5dNEz>hT zyS0}%`B#X}5 z6iPxOLu4o-^E{7H{@-VxecsMrXW#d}uKWAF_ug|pzV>N-_j=Z|p7pGG?{!+9d|xcy z?nH>o9oBi@%6IhzR>_gh|S^sIY8p8f~-z)fyh<+?L^ zJuq-wmE|P2FYnqD_teCl9s1t%*uMFF>jOJ-+zSSca*t}Z^UW~j_eqc?@`p%qxymIP zg5-HQ{iocHSw1(XXyvh&v%6~cP+YnwZD7yw$E|9*`bVV|pNu-~X&H6CU`BPgXWzJM z&o(dBe;==tqw@9qX)(F<41nk(*H=~Rq5GiA3$*sHcB*NzShoArcrUd+^8)=N6-GCi z;j%mB#&nz8^Zf1Kt2?M3pVDuD-92Sb=WY{jMVwrF`{LXrTH_Px8!ax^t)<`Nv(G0! z$^AI>h5UV=Mf0m(FKB(s&T6Kgi%rP#QjOI!4!-F3DzuH$N=x3^oQD@{9xAo0@oKa^ z%)8@kw{G!zVsdHCR`ij3^5oLnpG})zK2fhjZ>82J%T}m2f46^I{j`f|YmPn|bRta6 zw5YS?tgHsx>kCwlg*5%z`^=O3Npj7e9nLemE9l%neEn>axLh|cewAy1K;it8XLfck zV?E#4F8z(Mz`jw~;>(Xb=iP|#P(ZWCc-R!Oo zquZ~4aOK$GmS09GsULqczR0O!R~dUej-(j$L& zufA6c8@QkR*lCP>XZHlB;HkZ7>?G26vbbE!j5!nbjO}vddfwa<&CRO(*S>E%z{~E` z_>9$N6h##^bK67bvkvM_DjoF5@%7404If_lY^j#L_v>xVm8)LS+JH#z6mhvx z-XAn}E!*0!@W-pZAD_Nhe@fM0Mf8eJ1sg_0Y0ue_o7ug?gYbZ;mt!?Y8^0dcW{>*_ zH-(aO@;%dfbQx6`->&5gF}Vria((Vw`9(H)Q(&ucxKFaO<=E+uy-V{Abd=lwu-Kyb zEIA_lT(kPI``k|)P^dg*xWB#13(c%44)3mMcMPoG*!!9~t*MLjohmN(podr!9apQmCu=p@w>Wrl*+ZEMn>jNw2S=q(-DKjJ+|Y;=XRi-jbI`O6%V_=l_Z)2n|X)SKK=zNU*u-E?;OmK^tuD%b>oV-d_xQpO{-RNJs-~&EnfJDsh!bLRXNt>Bm@8+v zh1c0G^z4?r=NZlkqXrKeaJx#7s@!Ko=ET7ZI`$g0<@wGfOMQQ|ADHmbQNQ7?{Aj~& zrlXEjv`AX+IQ+SIyH4LlAGt;YRQ-{YjWAxpXPZUC-`Fe&Jvfqe)y&y!y6w+neNo> z?8s^E;pc-pS6k$dlbhOU?&KRi9m0%n)bmI(Xgzk1T}+a(wuk(qH#W&minA`>vY+W+ z?Bf1ZOfI!;qK{nWgsTzL29J8#FiolViQy%C_&aY*pE&u>P|Z+*`Qq;z2f7-!G4SvC z#QF5yUMjts`2-A4Jzrv7Gya9?+$Ra09k+|mFKDkw^pQJd+kDEDXG;feNSS3aazn)S zRw=4WW&4fnw`tp_b-Lqkz8bB+HhQeuoRk9RJ`sH$o@r_LaM*_hUGLhz;#>WUxTq?= z{yRrpuJNcetz-?3f z*DkNezcl_uxbDxVr(PUw;Wg#V{ytrg-{@)mWX2ff#Sa}9jJ7H{bFO-j=`dQ$5Xqe< zE_XzRwamzVYG;RjYL$KF(xVyqZxy$;Tg1OUbIN_**lfQ`srD65Pb+RbQJSm!!(2w+ zbZ$wLA=84dzSZyZsfDIh-e57g^Tp-H7_JHnZ#%&x=V*(gjlX(&s7wghx#f+*@=hD} z@$P)L*sR63uR8T~QCQFSE63Yz?H&8zMvp;L#+Vc&#he(OeQ#S6F}VxG<@&ch*0%G> zA^lG(8y2PyE!yhU@y6KIS27z7a$V!rd3)#5&0U|`jq5o5e!Dg)T4Cl|O?ArK^t!SJ54xdIeAT} zU_?PznR&;I-aWj&YhckBouvVzj-MT=B|iRLBraEQIPaLZx<_^Ejlnf*CjY4KFx$`G zUbaEySF3K@-wxS&c>nwR0*Cr8Da*Qa)s%luTo|6q7v>7&%B=PfNZ^?KPOVAjETA2+`HSb4T_mwb=213q01mU*k3 z+)FLIUDN=Vvhp>&jX%1I*r6lXkc`E_6gm?u3`0dHfor{Yn4_}5)~(t zbx!Hf9nCj_dRG3Psr}!7SeWOfef3qv%%z^&$5(~w_w4rUl9*gtQxtvVu4L({tkPQY zI4eVYDX;!a=dDb6hPH=s@LS}Z`c0-$-o>BPiR=10m zq1x}q>^OB_e4T5lxZGx0@)ZS5J>q_JP@QzC@@LG2w;NxKP?Rb7^4g&?@I`(bi)kB< zPl+r#+xP9G$%ZkX^X)BeSt@I6F?_TB!J_z*n_I;6T_!H~m0IH|lT=L3nIGC5>NR2I zrWZR5eJ>@*SEZLP8h^yK^_;LJP6vx-x4pagjzDGl!;k9GQ)ZZL-72H7VEy>cPTMv= z7n7SVF1LQ%k(FEQmR&EiPH3x`xqIBs1xZuuRj+Pzqh&~xQuFZX@`V}uzb$F(Rx$a2 zXUVR$whPV{|M)y&mPPDg3*NZW(K%x8`Ow;`=p*OXC!lTW#CjpJ<)(t!>*OmxRyiD; zf6>b1fy%Ntzo8C(9tZA@d1&46bMD7lrO=#Gc*`|h0p1( z5SJUPGqJr^=)1}7-22VCJNDc~TY2@p$+~y1?rN>=I4pepcE2W>!|%<>9qE~IY0Z>s z%kvXw-QH`zvZf}xb?4jXB{>Xz)LG+$k^ETe>Sgm+ zFBmw&)@j3Kn{$^8Pa%AX$U49>1 zIXoOXIz-d%^!&`C+sRXA>N9eg*A95JS1&%#b%Y(6hYLvS|GW74wz-v_J1l*n0JBui{0i7Z|zpR3?wN zR$Q(_fn=^e1nZ_ba~%}yQs-1eneKMVPx z6=!!OJgSHrzJAeibEERRExPnz^`+-&*NMyh(s9c5y>F|F!cBA{vU|SEw@;rxYNE+; zvyb75nq`AMc+Yz8nW$-Gsic_|aQ=Yxkhwu01#;rFD`dX z@w65vWiIs!zndLd>@4f~Me{Ik{_d5*CT^>}7c4tsaj2+^;`NEnvpP;aqq1cA;PKu0 z5yxeHJ9NIM&|~lHqT#wieVONfH;Bu9)a6BRjk9m%Y(wJ-UaKR1T$oz@Cc4Y8dfNv~ z3w|@S=Zn{Bg6_#((=0-VZ%Ebmn%V#Mh{7SZ?bOd$M$`*i9XFNw9vPnSIp~eza;@4f zjI;Lc>vv42NsYm#=;E#iyJzfdS^C`fvEQ4V%k4If-uU6IpW(?TU*p|_7ByRuonYv_ ze`b$ues1$J9?R++ZYiekCULoIdNys*Eyutz=Z<}!$b@@KFC=fib^Oup^YMi{2G?`0 z+2Oa*aGPJF2NBJ+HcWF@kRM#nSUbl>;Z5mbm$^<2^iBR;bYOm@_2aE8-rFuz-=5bbwd)Im^uifShMF3dHaIb2^oYAvUOyvZdQGmr zFraIIaNS<`Ueac9xeq3)KH6KpS=nob{&u4ig{6=6Z~iS{gX_VAZ+>+R=zq+VU9tNkXWbMhIv!uOK4iOXGiVBMi3y=Ob0_I=t% z$^G3NyJXGIA!~O$S@1%?dr}{(ad*20XgOtH$<5bz^kHPY(YW+a(J^`hOFeFE8?CIZ zrTdkUD||0$ySQBU3IjpgqcJVlS`TfvsqNHcdr!^9$F`Oajt|MvaojSv)r<4zeIFM1 zJ?I)_*x%uu?|a_o>bqYKXBudic4`=1Z{-74Uuq$Ch|5*vmHC{yu4Zv~Q0(j^i9K4s^It=78V?d|R|SwY##*-8EVuRe}9S96%s<8;T)bIT4q84839B2aWh-0n9xj}}3ExZFBQCdF z&g-?;*1k3M)#Mv(&1#$z@o@Y7YRAPtYz|twEE$=q@b$aQAzPXF2ruRI^LMPxyG}J3 z?ft%Nj!L2J+JnvSt*Z}NqItkxak=AvY;gKolV&--<&j~N)+Os(C8sXvGVV>c$fA*z zhi#m?o{mqtVdych)au62(0g*#mnUBE`0PJGzSEP1(Rv*$&)SH|-6t-$Sp|N!@SGrg zX}@oBeV5L-G}|$6OHT5U%^l8MZ2cyD;3$OwqeC=2<=-o&$u{`DJ>p2Z@#t3jaRA}1 zbmi5&%g(gNEz)}G8yt#VnB#0RrmT}?h|JSN-zWUEFbI$PhCvOzIX)7l8fVkXU&y~mBOzd!Ig;l%P_(-6h5O;jp~r3>SF7jepj2kGc>NrmdhRBkZX*YF2%fI{ZOf;l z@iTntb+}r*Qe%F-s^D`ceh$bv8$4Z1--F_Ey_TKrGvUazUX$f~(<`r3d_O*6L#LZ& z${m$I$M5~xulnkE8&7wy@cHWL-#@hOu0eEs*RxZF+cj%7@H99%K)XW~(lDSb9LExL2CQ%m`>ftOy6Fg=r!xFme^5Z8Lf zdfz=x2DaRBWWk7+tCS+vyH!6O5!c{My-$^5`sRqsH3<0FX~z69N8PL(<#aa3tuXNK zW7J0A*4<^_aqD8gO8)#^KWd(R>>78;qT%NzG7kefeZ8qVOr@=0+4U{Q3z7uF{#f{& z0+qHSARaa(PhcbtllHjR%OO5Gk%&Lzjaj~f7{Tk z{+k`#zhCPU<9O<+>ftW??l(5Lp4C}Q-{azPM-KSBeaxudR}atF`211vadqn!t?X96 z?>y*(#iO~)<(k-^i_6nazP~m5Zlj^wjT#E_8p|9#)7$;rh|%i`PJ~+L(i(}#A874Q z^pQKOx~xOqz(XdTURqh`-@AJ8<+rz4?Ox}Pj&7O-Y|U z{wr4OIgx(k+pB()+j)g(svaksisVw?A^OPe{3&PaM?obe6DNe{UYn?Wkk{Zyn9UHr=EwEj<6iBJ**#?T4TFtK=bW0@ z=eeDp)wvTEhs`fV#EZ$Lv6|>3=WW)z)$qY4;qw#BXZYN9wH(rFg=OlsgFm`IbNLx| zw`Q8$!A9Zlr|&hG<-bDR%qu%c<9lP4Vqb)S97L|6q%) znXBz)gg1IFUT&wv<$6!p^1XNCF*Xz2_iYWl*rlvAZsy8qKkKdk@HXg!&GWc*ejRsz z?{&QKsel~AO2Pc0BSV&@Xs**U3G9_u_AYS8N?E4M6wWsb#O03qdD%%ZB}I48GM^0V zbsYvQ)H$isEWO`Q!ywz2@2+l}8GiDI#v5b9TknUndR@c6V)K zS1P<&+MvB*@5&UpeyQG0C*+45FH5~^>g>H+HC`q0b({=;SN^-tpYQLp-LKS_WQpFZ zJ1Z{t!QA+{-{%eRcD%8ae?B?OaQVI4asdx6RvTZD!Oz9CYrdkWv485%c13o}&g}it zO}$m=!;u4~dwtLyX*b3u_0#Ddj9lUPw@_T}CzFbwchD@@yk8;<(G!JGjfIN59h?? zcE7j!!0jz6{S-p_-T2wWY)F?~_x(4wcaFH~IP~%RF|uC_?pA$zI%{wGQrU}YHv|3M zEQdK=sG73%uEJ97ALc7vDDU{kymwn9E?3^L@8Gbxi>4_n?)>DKnEhya3!j$Tn|Ddk z8@lYx#@0bU&2sX5PE}r&IrFGv^@e>%+z(_m!(P#sd0$*(WpCcjR~3_cUR-XJ>dV3( z+c)j`*tVdz!!n*>@}xyqH)IvL%t&l+*q zf$|r1R8BN&c-V-Qn}~`=b8yi|Zu`jjslyzPUTW)e&%M9Ks5^-bZiW_)Ua0-mwbk&o zU&=cUTw=OFHaDbcTH=$a;*8RVymoy(bzXMsUcNT7)r}P={&iCc~vL8K?7R|7F5^Q~Obc3|#7v$`- zY)waBu8EJHX+EuN?Q@eSW3?P#>UzmPR^BC}lshuKbez!7gmP(3QS_0EALn|1bfd+6 z`5o6jmlwSKv~2O|;-((`|KT4uy*fHO?zuHGPQcfftj<_I~sq^oBOPL z#_9#K*>M*eL6)dpzbr1-r2iq;=W>=w{l<1}*(|6_#PY8G--4Roa_+NNao^VgxApVJ zHoY|YjdK1=&j*ebo6j`fVYsw+;bHVZ8D%HwX7d3ND3@*$pH^{!bqMfpXwrL+{;}cWu6_ezYjSk$4k~J;p zEPGW{L!Y^J8Ra?!0OgZchtB4Qr2r~(6iTV3m0}!+&9)_>$9{oeY-~8 zww&ns=tFT-Re$#uFM8~l9pyXGdQf}q$zpOT4bev~cu|0f+*>XGy=OJmbid4h*HvHV zeC(UDW+!;YE*DN8l?~QgZoa*`e$J`(Te7rc3qQ0uq;DO&@K(u?$B&xc>=iUkOzt&t zx$}6pwks&}CfxhfBI{v-{^g5@1+km@uN|YmQ+dnl{QD6W)6dO3y=8Ua^x|#{+qonf z$+gu9v6*FeF68FfNS7c7cM9dokZ z`U>L@K2>oqR4xl|OQMu9FNc53wuXvST z)_U848pBR*vlP27jP_WjHlti|L$AcP-Z5uoTEveXJ#|Qc_r!>MQ$7GGYVW+>IbQT|1-xQY{IA-$2t8d;^ry1?( z+-mjm2mWWSdn-To-k4ebA~?N~+Tg1p^H;?`)H5>fxbLoD`09PDj5e%w+t&Q+ii~=R zF3MlOiOCY#;J@Qa$@m5b8cz`XcSx7Y{J&}eS}&rH=qmb7e~X7v_`maq>c{KmIGc#a zOZ<1%Q>vTP0>5hkOwo8M?RdP#@bR{|D*i9>b*jJN?RmT=|E75&{l4o6ZU4LF_s`-{ z8a?#>dAZVkK7paeA=1IXKQrlnnkSnYb^7=9zyEYbq&G?}Ahm$h0#XY|Eg-dk)B;iq z)Ug1~qoM;N`9$cr{%d1CiW}-38W!kRJ65N$qnX>kCWq3Ne*R}zfXa8@C>~Gg-*j&J zKf{W@rzNdH(%InRYmrn3`GVlU&`6w7ih8K|>k`T6+0l|R%clTTu(OTM4DaKXQ}$4zlxAP&V9 zJwHNWZBlr=7Ghxtl76HX_;0fS)d}fGY5}PQq!y4`KxzT01*8^`T0m+6sRg7KkXk@$ z0jUL~7LZy%Y5}PQq!y4`KxzT01*8^`T0m+6sRg7KkXk@$0jUL~7LZy%Y5}PQq!y4` zKxzT01*8^`T0m+6sRg7KkXk@$0jUL~7LZy%Y5}PQq!y4`KxzT01*8^`T0m+6sRg7K zkXk@$0jUL~7LZy%Y5}PQq!y4`KxzT01*8^`T0m+6sRg7KkXk@$0jUL~7LZy%Y5}PQ zq!y4`KxzT01*8^`THt?x1#GSfkCwi0U3hJ57Z@st^bQU-4i57T@(&E=8@osF`Q5e5 zOtb`nar`iULoEv}@8H1kp<({`C1v(g^HcbtKbJug3B&ISF(3My&P*rZ_r;mda`v8j z_$!9~!)FB>M!!!G!iKG6!|Ed}kPTbKhBZJ~Pxi+QGT5+&2s38GR{KQCfLy z7=Ff`=a297Imw3MEPY-H6T;)=vtc;Do_7tPv`(>Mq)!Dvp8__l6~5nPLU_E>2qWFq zfl4;)EPG#T{C%GdD`f9$gTEiJVMT0MTm1b2ptLTqaW(M$8$f9lvtjs&Zr&S!q{zU#m z{zCpi{y^nVWk5Ek@}%-38&dgDd650d-eh0OBjt(gMfo7TDgTsT${*!N3uq5$13G{% zpa*mS^Z^5)BY>Y*=5+=P0VBW|=mMAkrhpk>4p;z|fE8d3*Z{UbSD+hU2iODMfgV6l zpcjygjL!jP19O2{KoT$$5C9Q?KQJEP0|9^^5C~8mjs_xtD8L_}IvfU2y`2OIfC)f2 zFdP^G_yQw=NMJlL5f}xG0X%^qAQbQd{D9E_9~cY70^@*Szz4909^HW+0JRIf06m23 z16}c5AE36u6fgj&P3Q=i0A_$SU8$k7(>UCRy>TOd%8BhTf z07ak)paiG_@8DSPfe*kV;2H23xCjh~-G>40zz|>%;0zoDmj=uL9Dqe|&{@E2U;uar zAO_!~fj&S_pcl{^=nM1%9Dw=IdjT*7hyf-83BXh!7Kj59fp}mN5Cud7!9WNQ3fw>* z?gI~iM?g979LNVw0R_MbAQyNIya8ST$AK5XOW-l^1lSAg1a<-1&~F>A>wxvZMqm?= z35-R$;{XSsKQI7r1O@_w04HED;0(9`LjYI64Hycz10KLIU^p-W7zvC5MgwC2PrwW4 z3z$F`Q@|Xs0(1dAKp$uar~@qkRiFXT5ReDXpd8Ku)K;GZih%RL1wajQTL7&9b)YSv z2z*BVz5q2qPoNjj8|VY{1^NLFK!0EW;0O!^1_4gMV89u00X&h;SNO*STz3OYfn~sQ zUK>Zh&(rNDLI22c!K z1TF!afDGUm?wtSx0lt7YFaj6{j0U`bk-$}?`4aaZz%>idLYOgN2s8%dfbZb%0Jnjg zz-55?*gPN#*n@cOaqR+7|9BU;2UG(0fd{}l;63ma_zcka!VaMRJ|4ISJOlb6%nWim z07`%|paLiWt-(W8V{eGGgAo&axwr|kCtwx3=17J~5k zkNVr`xTO@h3S0p$11EvQ0F}uh;2@9ZN z$OBX!q$BB0c_1Gk|9lQS14O!0o*n|!hf`Tr0`~wa<8pv}fqajA@B~10`!qoHo$5W+ ze`*I{MqU8`)ACLM`9Ll}buk^FdZ`V_0?5WcewUN(r}0KZfMn432JE#xu3CT!&j1QdW@;zT-$hl{>bJW0GJ!Zm=_KwCf^5XEW3hKv5Dd&IxfI85}n zNQUTdQCegxil+lC1=4^8z;XIW?;g1J1RMd1-y7%y3;_BA{Qw7m;yD4%fGDmjz7GM00q%esFck0r z#sH&$k-%v7`#4<30$zYO-~;dhKY;8+_L~5ZEdziMAQ+%Udz95@E-2lfGbfGl7IAi8fizV8Bd0Na7Bz!qRLkO5=@8-R7d8ekQ$5+H6h zu$KM430Jz0`1R~{Bd*&3lD8As3*-RVzyUy{!x4Nx1k?wJ6NS^?JW&|QCK;l1Zs5Bpy<7Nx zlZB+TDKB>cO1A=_du{`gbk{;S-7kLc9sEssCLJZkA&%}Rxn#3n^B~fh>5zTI^T$=UL~wXU>cB!upYR^(s#ffNC2h)PJk^C2lNLf0it!M zNPHInv=%_~$B6*Vk7;gg1dy%6aWw%bJPZf{`~Y9T2cUbsftk=jq`ND=ll~-^)*ER3 zVF)0~2kAt*P<}{v$|LDddFzfVrA>LDe3I^zPg`)NxK6><23Kpq3a|t$0CV=c=AMF&;e-)DcgP!sE3HjX9>xJ<0Z+gS zAbrRNly}N+FhF?=0Q>>U4<8s0(7Hz;5Cnt*6o>dIvF}u#Br^sO$t9oQk~3zPlrH%l@rwYe3&f`aDFBr}rMUnQ-7k_u_fmSqi?}rCIS(K| zA-!q-;0fpg3xH|B65Kx@*Jz*y2n7;>NFWLb2mFDhKoH;y96+4CKsvAtSPCo#et;VV zbj0^PKo+nY*ahqab^zOfZNOGw3$Pi;1U3O1fepZVU>&d)SOcsEGJsXUN?--B9M})+ z14tLjGlBAuhieXS6gUD15Jqh${hbS(0FD920lJ^=Jq6?gl!r^WUIdDP3&44x2sj56 z0%w6Uz-gcWptgbHTmfkQP=f0i{;0ACVARF<)`vI5V;tzc6#>+C-#&)C4tURM^ zus3P-k9{4}+P%rJ?>3p!-m+k!DO17U306VlL=C$?78Yc@@1=mjvQHpb@0X68;{(8nbv z=WH%%6?4T<#8@-4T#OVGTQ}RWF!}k6FfiuErl!zqNv+N1S1iuVY94R67O6(wMTt%pBW*sapIoW3=+)eqb13 zCcN>%VLsl$0-o`S!^XYM3`!^+WYp5wU`$~HQ&Xm=Zi_fW9vnJsl5OTCEo-vEV@DlP91EsiXn?VA@nC){H3MZP4z#x9 zJ%qEj26NZp?CR%ts;g_`)PTWwI&rJv^tnSnw&}peL4H(GG03kIj}7-Xd{=LqD2^qs z6Btb}!~7q~B!ztY$}rH)oae~K+54eYF=Tb!8$33L+Kc0ZEx>t zm)rvkYKb}gn)bcO)~!a%p1fW2aRL|M3Gt)u zg{S6p_ud)v%s?g`hVk=`|5RI1o@7+u@$ux$B+)$V8Mi#v~vI1Ex_0a z8QQ_Yj3RMuhnq_~bPv4DNJE3f5FQwD% zV3N^;x8cpeSQ(pBIuU%|0Pl!Mfr-;`GnTJGkjD^@QkY0t!AEJ{0()K*QbA3MnV-Sst09F!f#2i{S^R6dge3bd8v zdEsD8jBQD`xG+B=ct%zaUi9xf^&}XyEtbaCR@5(3etvB!>RMD;CKoA_pYd>|k`vjj zmT6XBSaPyACMKr$GNY1%(Wrbhz)&2w2b+V^e6ofyx|vY}_iM>1|D)u%rEO!SJ>5E2 z>H75s$mt4%koCFaL^Kfk&iU4Fb;H!sw=lYyk*%kIQ9<0Q4gsGg#yOy7k<#!FUJ4kp zwfD?ZgSJGBh4&Hz7v*hWnWTFOQ^%?Ay$We&@N2XObz2JRFhKCK5r=GjW1HrK;}$!r zgwjwvyz^klvTGEBuOtu5SzMdWeK1r{7wauMSnAkoxR8O;yecs2U@Z4GZep$-Y9%W} zj!5aKHe_4N$I4nu8#Y5NA+6ycJYz7_hV&m@$xAvv3$;X)pMfm1CEK^>DaDIu$wiDm znD&UXVUu6@nVd-~LI%waZ#I|?U}Qc;G@SjlXE`xwVv$ZyfNHR4?9yDO6GG_Y1W-AN z#xAu?T|d|b`Np`HSI6H(Og~KLwQz^q@OoB*CJqgjl|i4)Xut~js`3tiD(Q)!dOp9Z51raWq6-=Bq+ zGiw=c8~oWa<<^Z`gFjnxzmpDkt>>2ZXYIya+T0raS-Wv-!0n^IQ`&!(-F~MA|5@FB zr{uV8{rBf*zk;xzD_CW6`s;LgJ*L-W#_>g9Xrx;1=QE&De$RFc!*rXGn4kLaunM;J z&h`y0b7&?(9Uc0gyNE-5iS_Y@hjQAwoCSjpkh;J(U}&6ZKg*?X?{cRR48wGe|B6Mc zAjJw&LNO4dvDlm}3+28R9n)E9&_JSYG;REsdKpnVf0eZP7~0ZUtlf&+_a^12J!A6o z+gfv!9EJgZCO>*8VgqRVJKoFPzH#f84_^~sb5NFP(@Z!DjKP)st*yC=joxM5)vz18 z9^xG_9N%MMWMs?u~tJ~a& z3CBGLK08y(Tw$dN<_xGgkf}Qv43eifzpe>^v7zNEb6z={j!D?16^mLyajyT!PDVQRt;8*0E703 zmdxg`(pIS*dfqzeSP&SL0hP}>FjS`36>URR)CM_%A+2Eprr1zE{=*l%ZavbuAEiT) zOii{S4ziROSFWji!Ph937?=Q!RY)A;I=m9MYf0}$MD+nld+h z16!r_%+U zf->$Kef^r|!M3m{CQTuM zp@HGv0)e1G>J;DQT_=ITng^AFE8@`HYQsJ{Q1{)~1c$z3Al7TuxTzFha=B zR55KOi#m77-=JP}syX7Y9xp*_tj|(uOVEw#DVR}^Mp}=O$tZXDvX)94tIeeKJvN<} zexp3@*yZ(QbYtSY07E(68D@GQ__Z&sp|EWgM>>#p4aGJ&9$SJF}1P$0ykdRZhts0F^h&?-Q`_#<)?t5GKI95fIwf`o4*jU z@XJP*_YN!rKL`}?C-K2-H5^_xROR`N+BnxBjXb3Bv*8*&*3GYC(qW|C#Zoxcmdcvq z-3As4%fZl638Z}lLo3_gn(>2bEQ(h!41C^%r=%rZ--&&feY3pBF=4BW9>anc1BSeJ zoTG0O?KvJ)x7qw~NweVX!(s?|$i@lLQL#0nH4q2s)6gLg40-R2J^V|ZY+b0}C@~!-PB?Yi_?QoR{Q2OFjt$wI!Vi2RynQjG;N>;H+2H7@Cz@c$ zI_BsxFl1-?g>f%`R;7A>X5+x)TXhubX8$2?Z;`TP02u0n!FYioKad+?=3d-j`)M$2 z>#_$7N$b>Qz>lw^o6~rdt@Ud=38gh&U0F7>;RACf9Yz}WxYx6@um_yym$vs<*}1z+ z9L9S?SSHtSRarNWRs+FMJw<*bjIY`LG=v{9o)2IBxLGAbcCkOTJ2VT0bvVY#@DL8& zU;|@A;YhW(>ELUlvfp$RuIgIC`u^U6$ceZ{-ye9@#Cd@ylMdQgTB(l`P!TEV_H*yC z)KKWX%y_46PN{h#X>X7YjSprw?6_v|#(l!oaAwTc%}CfLcGDc-6}NccAl3%Rp?7F( zhRos8a812g}Sz z0W0k=c46`ZA5{TEEz*`bulOCj4f?YTLNx)Zr<>j!dKABS;$bkz4YhnmEK?-YtjuM{ zQ|bY!E+DiU%cL*g8|cy2B@&Fe6$;2k!v2pV?xh(&uZ|5w%t72iqiAF6RLeoz+^J_` z+nv*FIvt*jFt)IpPCYtX3Rl5UA6(vidg)Po%vG)OKjE^<|OEy?IQPX?6!t$uvbee-9-S%Iz{i^-xHH{Nl4gAcFydxsK zW4o($vrztaej6(dvo8T%v%#R&`Jy#J^fhLorSyr_O^)+jXxf!}0=2O=XM9hAa zEBQgwacX6aN}r+65;65{g#FK##F_y^E{yvG>tG*}O8YJt8r_arP_VO})={b@Y!CPx z3|Yx&_jHB!-SVlY#i|E3vUwlDv;Z@6-MH)a+6}4XP#39@uiLta*3x)&YL*_*Cv&MQAqy>W^-R2J+zG->ZiriY=B<{Jw7xCtsM6In*wd(5D-5yUpQHxzi zHxa{~j>OdnW)vW)<--&V-Y7ArHZ<b*uyoDw~nusaK9aMuI&z|VJ>)Hv7mD$Hoc+bFK>X>*)dFS}U zN4lb=5HWQ%XwXx*Bk-#<<$uJfy9b6Iknu#0CoRxQ)P4Sdi31O*yO+a^L*R*ZbyMjj zd{UsUMMaFnkprXKdBklF8#pf?Id1dgR^Mf1*vEtEIab%enuu0aatkHu`ik5V#`M2*-244TUqAE;YHi7>jhy}En>K> z!|ey$d)2?QH|2!fDnsi(^CZmgXi&Ee5j|JKU2@#M!!7MjUtvzYUCT4>mnHN-nPM#X zAN7EoqW~i52hWR*cMz@`#(DTRTr{>BR(}4u$0s5V_3U|aGH32Z`D5(D z#6kb__dntFJG~5dOYu9_`2g$C&drm#ZN|uq?Vu*K4z*Rk(^CBX7UkBO+iu*ogu6%o ztLhJTI@~Q1cb((T>EB;++*W6_M?bsYM`q0a2 z^(l<-X>}j3@&Dnq!QUxU?l%7KuRq));@>HS4S)N%_phqKf3}6?_7Lt77k8`tSB<#1 z`=7r`1MV^3pPfx{dlk10xW|0lCHMEY2ftJ6f2ZyJ9lQPg*5UTIKWhW-TL1Uk;CDRa zcSc;l<00I$(7)eq+`jWW*5RI?{*K-Lx6L)V>(5tb;j=4ekJ(LXysjgt|+g;jgT8e?lbk;`qjzrTh3^^_{S1I4}- z6A>0192JgJJ%h^!C}sAdCs^_BG(B>|7x+X42K(`pb?p1ZH2iQ#_>2ra7xwG>KVayM zYYTH8#~T!Qlq{H!WBc$~X;<>JNTJ@_+S7alc*~X;wlHd_=hNsNh%4UPiWV~w}D zV)vxHS|*YoA)wQ+-c29%bBm5lujcghGxHp=AZomK1Oy%__Pv%{zi@YL987qbr;nhxfh`_ZeX2=PLqXdOErDl+Z$N8x3O8`S}Hnd!37<*?|_48V39Pf_dv_Fn_ z$KWB{?~X;f37j+O%y(2Ra|?_r7?a*B#~x~+BwNe8WYbY- z+4tF+-O*=j8QGyi-ST;_`*(OI+q0Hw0Y(MV0*}~jwP+CXxRxo2p`7k;2=t8Tp`TI9@WHeMb7j4U)8a=XCC%oaYnh{9C_hh@MZRC(<8w|ea{-Jh zm}I$~0b`qWom9)*Wu-0Y_EKlUf|bd&%m-H5$w!N}sR>1x`DWcaAC^hGP|FyCA>FK;E*xCH_&{7O^Ldoed%Jtd9=rBN9&fMF!*o;+>Wvom z^)_$gT@;mPUy+lc^F8U2Pi-*tgje>@m+u?5F4C)Ix`UzjPji~LQ1MJzF};=<2}T`E zkA|-P5y|KLYMBTy+F<6TRA(I0Y4*I9Nduz;=Bw9=1dEKKpS8>(FnB!{XD*ib1z-FC zPZa4^3WlDp-LEI-Y4S8lwU+q^MiCU)M1L}St4d87_!bbjXQ;<`}*MxOA)gb3_TCq&^bOPyyI)U&m>}g zJ?m9jCJ*;E!@b4uA9|`=be^iR%oQ;7#Ju-}XmI$&BbPMAp0@|~Lcf3)DCpokoN5>x z1m@C%X(moB#^AX@<_#o_-~9MKQFJ28!Wle^%GO16;)jLsojblD9KY^~Glg6Bo6zD| zvKbiW99k0|{lI4gnCEV1&fVm1#``~L{qgKC&f^tKjN(Vc@~)eIdaAJBfKPFR<3zq7 zDl#xwz?;JJuM82`Ui&k8KDbQd>p9QI@?viNMoKk<#>Y+=}0&?g5Fw! zG_*O4bwnro%F3`uKwQ)lpCB^frl#T$>=pCCb zO7cFMi}pWfq%kK6B!HpbOufNy-8Kf%X+nku%X3*~)e7AcgO_ai2!{G?2!x>%!2oSD7q9d z9t^!AjX1Bss34BODad17pXo_p=+F}joZ-weh0iQ@M(wGfQx2Gu5iEJl;5XEcKG_|+ zX!!k!^!^;07fMGL3`#GtqP@CGV|zuMg$QZPD8PngK9=dIt>5;5o=T>-7-1bJmRY!d zpGWnSOCF3gMz?WbsLzV=$lboQ;UzkKfOLb_I1YxXrFZr_nuPnlXTq2y3|$U2f+OES;zw29m`n7cM|x1)96?Ec4zQ=Bb1 zcl*ZODvyM(Qa{vuUfF$*3#T(t7f{yJ?r_%(TVan0rR20J>9p3B5x-X;CUYOw#@)WyBW@6-c>zKnFMhj+wD zH=AWfY3)y`Q0qc1A9PayL+{|`DL&cOf4?8KRTKw&^yetetsMj3kdfwSv`M_CdO{IYR9A%mQlU3LIcrpDC zTeHHA@N?rh59@}GUBjf<*|QLb-n2y=Fo7X~k-SfyL*`ctiaLQIe?zU$3TAufE#31T zC;8C3DOM)Li5SJvIVw)>#wc1D^Ry~Ke7X`-p* zYMyF;{1T}~=b_-OUFzo!LK@{Kq+>gu?P)$PvNEIq<@5>4no2InJ}r6T)!UR);n8P2 zZ{M&8a)eu7Qv8mtdq^dRmxIaSe8Plfx;(9C!L`F9S}}2$^AEV&onNIX%Y1+odJAGs zxKNsRe*4q?m#fpe%QUis4J7Kucsw@~A|MOkmn9AqlxE*Z831Xtjg7i3;p8NEHKnt2 zqOd*acgokdSpP!=;?VgaU~npp5$rvF$?brn3M0yk7~PmM zj@^CcSS!}2Gdd_g(2cvEa`#N!y^Q33fqdlG-(P?R^nNl_;2vLRMheH46$f`H`MPDU zLmc=A<#d9;h&kqF;jMW}-!|@~(Gyz=-0kRINK=K~Ty|ZFd38hGl97hmjXpSHd^nbI z__9i`ONZrG(5!%3F)$aSgyYd2?MG~=O8Th_238}xm4l&i@5`?~cgCv9TQC|hOdx6x zwN)>gYN`Om-DzA=8yJ%T(EFZ9HcCXapMml)Bh8t_nCIO*@SeB7sq{mz+W z5=ZNp0ik!EEL=YbZTBI!^ro(D?TlZ2if}DpQMseczANKq*D~De2X*HQ|9q7o1?kY5 zkiOrlE%Sm-pf?k(IqU_~9*oM>g8O4fYoZMiG2FV9AP%j&$ljhcdHEc3%Enc_ zZ0iDsdkv*7)7{Mb)lEmla9fl+ox0LQ<-=Wa z67oa8<%3eF>u;j@>7Vs$Zr!+TP*=BqUKb?KovCZ$&X4jm;Tq(kL#Iv!YMbJDK9NPa zSM#{@V+3i`Hx`UE`OFeJ&gKNzx5egmaAl?^I}JF2j8WIL8^& z=zlm)u>`Ysx^T3i)W@M*$^MlM)63v@d2D$nz)&yKLiMqeLGl0^hu|PLoXUdMQqm4C zm1z+xEq|(WW!T*uFT|k{FMgkxZ1mXFyN%{4{8u*Sr}7~i_i zuce`GvomCgr;L&UT&u@mB<_VWaU|}AGK|E%P==AX7s@aa_d*#);$A4jNZbo$7}=r1 zIpF`d7s@aa_d*#);$A4jNZbo$7>RqK3?p$blwl<9g))r9y-ty z{wc#q+&^U)g?YlYZ@tr-hw8VPASbF>wmbtc+R*y(khpq-Jyy`O5lo%qs*TiK*6lIq ztXB(od|hVX0{o^cG5ivX>Eg6SFkSj0t~eWVaqQmB_ungGmIG> zx+u3$$e1tojXSw|9ag2j;9dpXs|<#AY^InQYv!xg(?%Rrd0MBCcycV$zWv(EFg-f6 zf>Ae}SCCKXRN+c1B`>;pd!I9Nrj-)fpEI>KS4tRw zd9!}YsKUv@GfSDi1cwBB2YdVRe*~YZ9z1%|Sj3^#2w0TcZogVbStbecX$15%^K9Elo0KwUCwhfO{!Fzy407vWyz;r5tAAN~Pei{pYr} zdwbJ5A6XPFYz`P&nX9mLjrDB3+Ky%Ldj+T2xZ7-(hP$c1Un@tat1#{)!Z>SoRRmX!^T@1aw7}3#u}9NqN&Jy<{c9Op zFdATbmE1j*F?w@sEi()Zm4g1W^Tjh%2hXi#f>~)At=B%=k)zeFmPrCbD`p|iR!yf1 z2IC0`QGV94%z;(8H*P=PxU!Zx0*35%e%P|&l55k)(z(aX51?9eTeK&7CW<3Er3#)% zyG(Ed?(_NTrwezpkI(<;(ELp-R+u_L3Vr@xb7v1LS#s5J+eA1p#_5ja3#Sq>1py081b_wG!0-`>96Z{{r)!V)psz!D!35)hF<>c|p;h{O;O zAeo%Nq)14H-#Mqg?(N%E-8~6AtJhU^>-_6f)v2#jRi}Qy7eV{^?)`uI&)@kAtOord zJE0=jhxZD;_GhMb|MP#S|Le2w{)yCc{ibMbfI`pP&5&^cCJAd%k-~HQ1zx*7()WP?E={sNg->*LV$v5$T8UH`N`1squasQ2f+lqN` z{`=AYeD!ZOKltpc*X`<3!hYc=fA#)Pf8~=OZm}S~VO9S7|N7|rzkBno|Nal63*H~U z_w|4N{F^WR>}~n~kt@r0zwmR)#~0t1w|?K5dg@odOF!|k9y|RQd#m%=>f>#HW!?Ve z%l^u(-gc|K4+~PM=54*`Zuh?R>jqk$C2708Z};`K z-i$+Mcg^h8b@yg3ob!(Lx^KzZ{-@Qpd9$sS&1yIPHqF+2)2-*2x1S`r>kzh*p;R`q>*E7_h-WZkVLnK9UUgA8%vavUyo(N(vbZnqwP>SuBk6qCD6 zz4xhEQ2P6!sOal$x0g5~HQ#5cUv&EruUm|SkAb)K^&aEf4x8qC5xd*l{c7B5=yWEx zUANe_YZ~0D-`2BNPA2ux&}_j$)at(8wDoG%R5YKvZqsfbn&tJPmU`@VeY3Fk)vngN zZPjgQP%|=Xfh!RnUana-y@~p~eyG;%>{YXI{%&awX(g336Z2A2?Wfw-*7d4cIBL?P zf0h>R+a6+u0eSDEv#9D-i=Fl6Zo6Ig-?$_nZ>k2U(9wmRR@`b&5LE8=8G(j=fvy_KrCG-tXIq&d>PFSfC^-K%ERXMjT-P=mWt z@I_)+0A|uod?Px#TB{=?Y)6I50DR=8VnpwAGu_3MOX0Kx~ zvfCZq?B2I|+b`R`*Os-YANKns8Z>siS6j)g#-dZ$HV35L#2%%8a9ljDHnWVNjI%hM zT&Tn8&(tX!#!{tIaLvt)42=42!PIxMO*c|mv=dn!&6S&{2_yE86#khZbsC-#qF0L6UME0i2SC*id&*y}O%mYqfQ43%|9C+OSbaoM^ z><{qM4`-pLZ89LIfr@%+#f9!DK!%Wtl{gBH(*!{#9RW%_a3xQA9E%cC2PC-9%30b^ z1&-3dw?NfSa|Ehkiuvx*xwSEXHG}rt0ni61nhq`}$hjLH0+{okm0KHt0+e|b=|v%r z6Qf&z8H{;InH&*9J|;*i=I0iS)qhq-J;Tp=gn3I1z9+Bg{|?p&=axC=Vr!acQ}1 zjJhN_k(_U)lT`uOWH`BV4WAh_MZ?r2lg$tZxZoypqQX0dsi90EHi50ZFEI9${e4i6 z6_pI%;~}b*$-k9HJJ-r7@t@2aAx(Tx%hMzI+)u1cK$!^DvecgG!w>4H$+BLwpEmkPO?UlL+7*Wf?^xD#`T|Vv)ZkUi9Cfqx zzLz0<(baRAWPteTC+z+1&7aTct{s>^f~K zx>U~u3Nt%Z2j?Zqy+sR#bLm2>w2EDR3c>Qz*ro9xS%p%BmqN2jxQ8_sTcO_W`ns@!YNQb*m5AXTcaUE) z14jc`zmnH-wPCIasc#z&*PPv^sBUPzW=D^)c}~xSYA}a6h$xVQ0L@@& z`4Qv_^58~MCOfGV%~jji^{kh%XxCn?U)_q9T{>wF^5lei92N9HCcU1NeZJ%eDMPLt zRI;a~SwhE0r(L~n=i56}ecwp^SL`oQnrToqd&xUhDD3IjnX@_q^Iho$hB892EURw|uG=RhJ~phQolTV+y+3PW$vyveWpK^Bu%X0F~~juFT(nfY>{sD^FX)ss_T~K5D{y zHN8v%Cs{Nh^G|Iilt%ASFX+3agTQXLnKdl7bVQh?pSJQawqJ*3YX2Y&ObsxUEw=h- zizy9Sy>7wY4p-8SOr;+(O**3xx?Q)dJQ6YC0kp)Y)mf6}G&iA?g)3j;@Z-7>X;Th9 z!-?V8Bx+L5m{k44lC{t)yHJ=(tw1Rm z$z$u3w$y+lrvOHe(v~#A!#qPj44~=rkZftbgm#3T5QxnY`>C7VYNqEHsGNDGoCfj0 z8TiSERC0ctIiOjQ0_pm#?3<5tE=(sKsu&5W<_(oASAH{G4kH3R4AAmcK1CEsl8vGa znneJ`9LM#FE-$7{N-}2we@~%TI3hhCOhlt#hkJc4kkjdaG$croL#@CvEQRNx>USOdSd-%^|Rte6foVaEb0?KZR~ zea!oMu@j}LXgtwRqvsK2ONPl93Ha#Ic2?{YIbHxJe@G1IbuvupA-!*z^g8Fm!PcS!(Lze{Up zmj&X)r;41?cpf%upbc(>$eo(HlGT&!8Qt_3a)2lGzsBxZCQo{x?g_BwpddvZo-fCQ z`%zxPnmm)@m^sN(e<5s2E!x~Ojl&U<)x6Cejgu1j#Ffk^fN(^wl!Z;R>#a|8F37}U zMLy#bY#H~CN0kI!cWibm>D$>LX>!{tX*7^huNH>(>zvJGq|iPKJx8uGM=?Phg(#>B z{E-zT(&Vy;i~KpwcZQssoKWyrY61z(7irv(6r!*@sf?Cdg};{xrFYUM+;$X=m2RZo zu18;L$@W5S z2II0Cvrr9b@71&$TVGscCBwOW*WJf?qHn%#4l&WsLFAZtfqXwWnqwqWGb|M(^ zVE|cma*(MBcFtCf9853=GWV`^0q*ilav~*h=1)AbY`Uvi9fRtfQlny<7jZ&R*go%< zUB?#cJ!3(`*;DqGpN6>fBpj$|*{p3>b`pDg-^%9rLq+^~r^ji~eH%lW<20Fk4*}tH z7*IWZj#WmjL3h(){?sXS>^=rwbf5l820q;%Uw4>qN&+<}5rA7CoNEmL+jcqfZH7P@ z{)s5$Qghykh?X}pT;xcmf?aA5P^mV{$kYj)I|-sWU$H{Wup8ol5ZnlbD9`d;3`uLT zS<>p%q>o@(Iz1y(6^QQ4ACa0!pG!@gIzduNK!!!?sz*;@N)GPVTN$l2MCNVpxKC0s z?t7+4Tur!$mS93jvgJJqFcP^lj3nS#iO>xdqqe=3Ba6z)zzEHKtTaj6F*27SKqneTz}6GcMyYLKn#sF)@%N zKlj}J<0#}wX*#}yCq(1;x}EH$N)zGXP(x`90~iyJnF-mL$K3_%K8B+i>Uc5M zM_0#rP!6vwSk_@T@b)gZ8#Rt9^)#ZU3oUDx2BRz>1HXz*NjsK~*#M+orB_+eMOpL7 zu3liXxm#D-;4CUz6HMP!@2l6&GIBIc5E30Dk-RI|t82MXC+i1k)?ApX?wZA#gM^vH zBA+A>J))|TE#dsgWSq7(&5=0`lUS}uaaX%UnJ`DXiBG3}C2I6|QnXMymv*|v1~w=j zDNidXbQNq9soFsH;+PD|ZNAEV&6M3lY(d?}K=!$fRLWH%J-{TssE^4qV-=tr_`1L% zQZd;@H|HQHWadDeSUICd$yfbs(Z7L4eq?4_OvOYc-sKBy#vpVcVqirQPGetjRG5pi zRL7;o%@o33TuH|64>C_FYdq6*#~eoPG7LC?(M84xHTs}Mr-%0C(6gAGEY9dpSc8ZZ zge#VThY*6?KX(;3JaTPGxQmW2in)!~J3|^VNDh{`O2v@H6OL{vx>UvEVX6}1QWj?> z**PnW>SiU~j(5@llvjGm#Z*WWpKcZFbXr+5F5Y#_WEe?ry@Hr}Ww?9p7O(=!80BC` z`Ls~I`;cE#hP$?;6x@u=qIsvuq?{)OnZPH`d`eR{eMxjGnCf-qKKwfLp_WD#xm{W5 z;{$v3?utfjRU}*{&eItVsU6@ve2-bk)bubv`;eg+G8nVv{1ue)L$!sL=iAxQxjl42 zTd)t@-9{SA+R(|{;DB16rgy^`iQaR)XpC)NK#$-#{5DYz@` zfnVpRq~$6T4P<;L1d{>GjmDw(ZO`;=@!;+ZpTNL~GB7d8$M= zC}2gZL~natZSTmxst@Reb2&xU9b8yw>vcj#dUs}q?rJDj41mj6s~7% zfF_)tj5f22kjGL^7F*y#CayC3(H?kE#C*wRFNGy4fC44!Xm?{LjUY{H0It30vG5w1 z1oW4Vz-_J^OD>5+t%rbwKiwwH5sySyr7ski`n1kU3$C#|rRFRGTpDPSpriPh76m<` zGGS|F)7?vx(EFz+RQAjQZomHHnNCIF8G3E>N|1pPF z69LRsj0|$6JE{9fY~&?C_~3|ER@|2xNuJnGi8y#HV?|ZU2&Px#ECI;8%8{Kd97UI& zieppvEoM?q5UG?bq?HDqRV!wKCg7PDB!6Br@Lt^IkF{h`!8FHtd~uRcSJ{y@AEJ1t zb`ExqEdi4zM$as|q5L{F=F3K@#QaZ$Q!^lH5(w^iisD2}DP?DEC}1XGS|6w87*&m0 zHVS|~;H>g<=940rnNw1%liS_MR8s&Qg=iov(WP_9#Cp1KfK0r71 z#;J0owygq=`V{EYdXCn!0$2<>uYLyBx&rDT^t?QKn+Ag-Oarw=qFFqx%4MW;rpf}h zNthKvNnbT?=X!+~yJ!*78A=20bSp%)+FlD-<~7D9CnVCbqbt38n9~b3xl_PnzDJZH z$x%4-JhyiyANq&YOivJqnL{p{F{R72hyxTPb>IsbJ>vX(7;CJftrJsrAs1<&7T>AO zg`J0BJTIaqfmSJ}P9=h|zKH3~_W{Vn^(O;wUl7=Ct-o%n&{?wbq z06>0NE~Bz_O2nW-`S1gIy!hg=?y#(wQ^S(-)85jHpwtSIt(kmj+?HY&8z+cdM=+ z#G>?`J{gstg$*)iLBMAOAg~uABMZTuNW<|M!b1QN&siuc9RWstC*p*110}dm#7OD` zl*D%;PONHRqUS^u6E-Rokl;QGLq#*7sP8NsC-?!$`Om`Ah82+1cNUIsw*krroQ3B4 zh5+XLXJNUPVO4iV%P>OUG7{fe+<+5uh5JN|q#Fh$@tuj|bLElLe(u55s8!6I!qcviSJAt&yq(vr;HL>>Mik|%9EcI2#R+n7;3{sCLv-QbC)~dXAyug z2m9#EKy-QQju2t(h?&5Zi|1mcoHzA#d-yZs@{lyG(dkcA*yuxOY}M^*C+Xc`&QWvb z*^V)myMB?6^8A^=90K60KumsKcdwg`%*8lecnHFG!iT39lN14s;xi0Sr0G=X!0;G5e0U4+SXg89_~k5k6GLB7 z5quc_me9z~6f(hY0UX3~3>`ka1$fdX#_-9fw@6^rFvp3EKEFjmPCn=$#%aVaZw)_D z!G`{JRSbsqAJ#ig@Sl8ryFA2hdMXuiVJw`LNSs+j>=^bokXpujpjPs6SUkQXO9n|@ zH0+O^bm(sh%w>jaxk$K=tzV9Ww4e=!H0R2Bd0oHGNq3so7aL_hP9kE=Pxdvx+7QJT6S3F9A~@SZTMe|RiY%&tjJ!r zD=Re*YzH4N^zP%;-3|+oH}>3!p25^N=Jil7csnlhiRl`-!|CA+YBS?Xu9))Y-2uDB z?Z5Llf;>p_s@=MYpc?BFyZ6i5vB4RUR?eJaKRdjKVzx3-k8J7(Sbeaqb`laM9EDf{w3*;LP(!~T8MON7^4wGESai{k-&-`3d5a3 z&d{dg0Mx0M;a}{?298_W<@ zJGsE@Tu`}Q1*6e&)LMEL?OnvG<2HAyC5Z)I;-mZ=X14r8a!@CUt9688qpgfW5_Zm* zlT4~amZw;ZOk8@IL{od{xN}?S?fDEq5(|*Tr&U&Bdpv6ZVjRS*&lTPcmurhAVqzr0 z3KUuerQV1Mh}_$kAL6_F$~pvJ?|5P*XMZ7y1w!Iexi2Lwe6kbnIK~B4`R>YSf+o~* zTr5u6v@T0+uIc?5N$1iIw@jr+mPxbe?eMZ3kJRdxX@8A5&_1`#9wRA)r_eTA5}Jnl zWsPhAn?p<^yY2p($?b~iSI!Kqo1vtWPKDArbQ*e8s|_iF5!|uonVRXaj6k4emahbv zwx!<#Fn3Ahv~9i@cDeJ9fuvq-NZO0b(`4AkE>w_g=KVm!h-k1Cn^rF2*PWr#pFbdsc9z~r*Q0(Ie4`SzA!3KNmEB=F4vL*+|+ z>)q->7HLp1q^I{e`)5`|!)uxH6XF z3d`i9#!Zi*6~tBIxE9LPs3)>cVI%5x?~J3qGuFlqUVkTTRqXy@U0+sstnPEupNZI{ zFcGSWX-6iVAl!?cyu7Z%MFP*cw567+3QH`i^?}Sgb#N>OkZ)w8#?Ez zKe*m>G2% zPG1C?bBXY|8*CYt98Nl=0AeDPQg?3+WYAm&6K&NbTjd#oFDX~>PD>VR!UY`Hm8rgP zsF~AZ5;dT7)TL?Uh?xUI!B%pqse7P7eZ$JYuk~M2B}`P%fohYxr=_lBU+D>0It&_N-qiPqGq$Q(r-6wM zU#mXfiF$E7TvvWTyE=II$t3l1n8!Nj+oA*l8J-!Xmz`teKA~ zq?vkUuE}Uy+F=-^3dF!q&dYY({3QUP)oT%?jP)aJD-42mQ^K9>)&mV+V!YUCl+$p+@q3sF?h|w5i;<&kpd`LCaeS^k z(mDBxC;4G1dQRjhm70ii4nNE@xCdh;6x=6rV|04v4rUVHSvc-+T|n}O?M{;)BGjKu?;XV<=ALKV_OnhhJ z_*{7;^`D3pPwA1d=s6F?Gvsj2;m4oPvocD2CvxN|Jxc@s`B)TEf^;g5zZ4)S-hCv7 z864F40@V5|yCH6u&`l>y+vH{s?6u2NAj3~Qw9#VdjPqeU3yp2Zn>ITqEEB_wOLYob zSd`;@`N`KX7142HNF~glr!tk`UWi$8UMj_0rK8C&>0Dv~-W*nzCB?#ovKC`(eby z*`{k{p?Y{zH(+<$j=kiY_Dxo%>LeNrre1rO*9=D9@Q9lnyred-F*=1LbK<=JuH=$EdO@dbc4lH;%iiHQNYyB?FoaX}Pu#mMX zPCa5+TTa-aMQ)704Jq=6mFUqVcFx3!`}wiZq2AHq_A>lCd$T9+@|&6IZeY( z#S84j%J;AnpH4*|$(%&hJITfB#a(vhyh(U>)h#U-fi6Kp1AY3{d!TiE8Eom@PjZ5wu=v& zUWQM(lq7?0y;$Ed>gtTwhv`84P9~q; - - - - - - - - انجمن علمی کامپیوتر گیلان - Guilan ACE - - - - - - - - - -

- - - diff --git a/next-env.d.ts b/next-env.d.ts new file mode 100644 index 0000000..830fb59 --- /dev/null +++ b/next-env.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/next.config.ts b/next.config.ts new file mode 100644 index 0000000..a807c0d --- /dev/null +++ b/next.config.ts @@ -0,0 +1,25 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + output: "standalone", + images: { + remotePatterns: [ + { + protocol: "https", + hostname: "api.east-guilan-ce.ir", + }, + { + protocol: "http", + hostname: "127.0.0.1", + port: "8000", + }, + { + protocol: "http", + hostname: "localhost", + port: "8000", + }, + ], + }, +}; + +export default nextConfig; diff --git a/nginx.conf b/nginx.conf deleted file mode 100644 index 142bcf0..0000000 --- a/nginx.conf +++ /dev/null @@ -1,33 +0,0 @@ -server { - listen 80; - server_name localhost; - root /usr/share/nginx/html; - index index.html; - - # Enable gzip compression - gzip on; - gzip_vary on; - gzip_min_length 1024; - gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/json; - - # Security headers - add_header X-Frame-Options "SAMEORIGIN" always; - add_header X-Content-Type-Options "nosniff" always; - add_header X-XSS-Protection "1; mode=block" always; - - # Handle Next.js static export - location / { - try_files $uri $uri.html $uri/ /index.html; - } - - # Cache static assets - location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { - expires 1y; - add_header Cache-Control "public, immutable"; - } - - # Disable access to hidden files - location ~ /\. { - deny all; - } -} diff --git a/package-lock.json b/package-lock.json index b37b414..94dab25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "vite_react_shadcn_ts", + "name": "guilan-ace-frontend", "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "vite_react_shadcn_ts", + "name": "guilan-ace-frontend", "version": "0.0.0", "dependencies": { "@hookform/resolvers": "^3.10.0", @@ -46,16 +46,15 @@ "input-otp": "^1.4.2", "jspdf": "^2.5.1", "lucide-react": "^0.462.0", + "next": "^15.4.6", "next-themes": "^0.3.0", "react": "^18.3.1", "react-day-picker": "^8.10.1", "react-dom": "^18.3.1", - "react-helmet-async": "^2.0.5", "react-hook-form": "^7.61.1", "react-markdown": "^9.0.3", "react-qr-code": "^2.0.11", "react-resizable-panels": "^2.1.9", - "react-router-dom": "^6.30.1", "recharts": "^2.15.4", "rehype-raw": "^7.0.0", "rehype-sanitize": "^6.0.0", @@ -68,22 +67,20 @@ }, "devDependencies": { "@eslint/js": "^9.32.0", + "@next/eslint-plugin-next": "^16.2.6", "@tailwindcss/typography": "^0.5.16", "@types/node": "^22.16.5", "@types/react": "^18.3.26", "@types/react-dom": "^18.3.7", - "@vitejs/plugin-react-swc": "^3.11.0", "autoprefixer": "^10.4.21", "eslint": "^9.32.0", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", "globals": "^15.15.0", - "lovable-tagger": "^1.1.10", "postcss": "^8.5.6", "tailwindcss": "^3.4.17", "typescript": "^5.8.3", - "typescript-eslint": "^8.38.0", - "vite": "^5.4.19" + "typescript-eslint": "^8.38.0" } }, "node_modules/@alloc/quick-lru": { @@ -98,42 +95,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.9.tgz", - "integrity": "sha512-aI3jjAAO1fh7vY/pBGsn1i9LDbRP43+asrRlkPuTXW5yHXtd1NgTEMudbBoDDxrf1daEEfPJqR+JBMakzrR4Dg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.25.9" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/runtime": { "version": "7.28.2", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.2.tgz", @@ -143,443 +104,14 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/types": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.9.tgz", - "integrity": "sha512-OwS2CM5KocvQ/k7dFJa8i5bNGJP0hXWfVCfDkqRFP1IreH1JDC7wG6eCYCi0+McbfT8OR/kNqsI0UU0xP9H6PQ==", - "dev": true, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://package-mirror.liara.ir/repository/npm/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", "license": "MIT", + "optional": true, "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz", - "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz", - "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" + "tslib": "^2.4.0" } }, "node_modules/@eslint-community/eslint-utils": { @@ -849,6 +381,472 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://package-mirror.liara.ir/repository/npm/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -914,6 +912,180 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@next/env": { + "version": "15.5.18", + "resolved": "https://package-mirror.liara.ir/repository/npm/@next/env/-/env-15.5.18.tgz", + "integrity": "sha512-hAV85Ckd9QR6RvH04MEKwsfLTksvFpO47j9xwtoIuvuPnlwecpSi+uZTtm8HirVbtlI2Fnz//xpcSTjFdyJk+g==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "16.2.6", + "resolved": "https://package-mirror.liara.ir/repository/npm/@next/eslint-plugin-next/-/eslint-plugin-next-16.2.6.tgz", + "integrity": "sha512-Z8l6o4JWKUl755x4R+wogD86KPeU+Ckw4K+SYG4kHeOJtRenDeK+OSbGcqZpDtbwn9DsJVdir2UxmwXuinUbUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-glob": "3.3.1" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://package-mirror.liara.ir/repository/npm/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://package-mirror.liara.ir/repository/npm/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "15.5.18", + "resolved": "https://package-mirror.liara.ir/repository/npm/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.18.tgz", + "integrity": "sha512-w0WvQf1n+txiwns/9pwIQteCJpZTbxzO2SE0FLcwuD4v0WEh1JPOjdyxWL21XwJsdpx8cFRjyzxzCS/siP7HcQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "15.5.18", + "resolved": "https://package-mirror.liara.ir/repository/npm/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.18.tgz", + "integrity": "sha512-znn71QmDuxm+BOaglihMZfvyySMnNljkVIY5Z2TCssBmm+WqL6c19VhtH5ktFkHa8EZ2bnTUpcNcmNSQsg67og==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "15.5.18", + "resolved": "https://package-mirror.liara.ir/repository/npm/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.18.tgz", + "integrity": "sha512-yPPe5MNL+igZUa+OsqQJisqSfh6oarIuA1Q0BDxljGJhRQyZeP+WRHh7rs/jZUGMh5aY0YdIjXZG0VohkKkUdw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "15.5.18", + "resolved": "https://package-mirror.liara.ir/repository/npm/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.18.tgz", + "integrity": "sha512-glaCczEWIrHsokFZ3pP08U4BpKxwIdnT+txdOM32OBgpL9Yw4aqx8NejmgtZQZOdstQ5f0L3CasIZudzCuD+nw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "15.5.18", + "resolved": "https://package-mirror.liara.ir/repository/npm/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.18.tgz", + "integrity": "sha512-oUfg2EgJmU3R0OCOWiokGFUTvZiPfXtriXiuF3YNxRoROCdgvTedHIzYoeKH34gsZxS/V7mHbfq2hpAHwhH1/A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "15.5.18", + "resolved": "https://package-mirror.liara.ir/repository/npm/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.18.tgz", + "integrity": "sha512-JLxSP3KTd9iu/bvUMQxH7RJo9xKSHf55/6RPE4a6FTSZygGn7uvZbCej0AHXydwkggQGSD9UddSjwv6Xz5ESfA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "15.5.18", + "resolved": "https://package-mirror.liara.ir/repository/npm/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.18.tgz", + "integrity": "sha512-ir1v7enP52K2HNz3tQQvwF+x7VNxBk1ciiZ18WBPvxf4C59IqdfmHPJYK3vH7rSxpuCVw/8C712wTXNAtEp+NA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "15.5.18", + "resolved": "https://package-mirror.liara.ir/repository/npm/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.18.tgz", + "integrity": "sha512-LIu5me6QTANCd25E7I5uIEfvgQ06RK7tvHAbYo3zCb3VpxQEPvMcSpd87NwUABDT6MbGPdEGR5VRiK4PPTJhQg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2313,472 +2485,6 @@ "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", "license": "MIT" }, - "node_modules/@remix-run/router": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz", - "integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.27", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", - "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", - "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", - "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", - "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", - "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", - "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", - "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", - "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", - "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", - "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", - "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", - "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", - "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", - "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", - "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", - "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", - "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@swc/core": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.13.2.tgz", - "integrity": "sha512-YWqn+0IKXDhqVLKoac4v2tV6hJqB/wOh8/Br8zjqeqBkKa77Qb0Kw2i7LOFzjFNZbZaPH6AlMGlBwNrxaauaAg==", - "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.23" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/swc" - }, - "optionalDependencies": { - "@swc/core-darwin-arm64": "1.13.2", - "@swc/core-darwin-x64": "1.13.2", - "@swc/core-linux-arm-gnueabihf": "1.13.2", - "@swc/core-linux-arm64-gnu": "1.13.2", - "@swc/core-linux-arm64-musl": "1.13.2", - "@swc/core-linux-x64-gnu": "1.13.2", - "@swc/core-linux-x64-musl": "1.13.2", - "@swc/core-win32-arm64-msvc": "1.13.2", - "@swc/core-win32-ia32-msvc": "1.13.2", - "@swc/core-win32-x64-msvc": "1.13.2" - }, - "peerDependencies": { - "@swc/helpers": ">=0.5.17" - }, - "peerDependenciesMeta": { - "@swc/helpers": { - "optional": true - } - } - }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.13.2.tgz", - "integrity": "sha512-44p7ivuLSGFJ15Vly4ivLJjg3ARo4879LtEBAabcHhSZygpmkP8eyjyWxrH3OxkY1eRZSIJe8yRZPFw4kPXFPw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.13.2.tgz", - "integrity": "sha512-Lb9EZi7X2XDAVmuUlBm2UvVAgSCbD3qKqDCxSI4jEOddzVOpNCnyZ/xEampdngUIyDDhhJLYU9duC+Mcsv5Y+A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.13.2.tgz", - "integrity": "sha512-9TDe/92ee1x57x+0OqL1huG4BeljVx0nWW4QOOxp8CCK67Rpc/HHl2wciJ0Kl9Dxf2NvpNtkPvqj9+BUmM9WVA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.13.2.tgz", - "integrity": "sha512-KJUSl56DBk7AWMAIEcU83zl5mg3vlQYhLELhjwRFkGFMvghQvdqQ3zFOYa4TexKA7noBZa3C8fb24rI5sw9Exg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.13.2.tgz", - "integrity": "sha512-teU27iG1oyWpNh9CzcGQ48ClDRt/RCem7mYO7ehd2FY102UeTws2+OzLESS1TS1tEZipq/5xwx3FzbVgiolCiQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.13.2.tgz", - "integrity": "sha512-dRPsyPyqpLD0HMRCRpYALIh4kdOir8pPg4AhNQZLehKowigRd30RcLXGNVZcc31Ua8CiPI4QSgjOIxK+EQe4LQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-musl": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.13.2.tgz", - "integrity": "sha512-CCxETW+KkYEQDqz1SYC15YIWYheqFC+PJVOW76Maa/8yu8Biw+HTAcblKf2isrlUtK8RvrQN94v3UXkC2NzCEw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.13.2.tgz", - "integrity": "sha512-Wv/QTA6PjyRLlmKcN6AmSI4jwSMRl0VTLGs57PHTqYRwwfwd7y4s2fIPJVBNbAlXd795dOEP6d/bGSQSyhOX3A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.13.2.tgz", - "integrity": "sha512-PuCdtNynEkUNbUXX/wsyUC+t4mamIU5y00lT5vJcAvco3/r16Iaxl5UCzhXYaWZSNVZMzPp9qN8NlSL8M5pPxw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.13.2.tgz", - "integrity": "sha512-qlmMkFZJus8cYuBURx1a3YAG2G7IW44i+FEYV5/32ylKkzGNAr9tDJSA53XNnNXkAB5EXSPsOz7bn5C3JlEtdQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/@swc/types": { - "version": "0.1.23", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.23.tgz", - "integrity": "sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@swc/counter": "^0.1.3" - } - }, "node_modules/@tailwindcss/typography": { "version": "0.5.16", "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.16.tgz", @@ -3256,20 +2962,6 @@ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==" }, - "node_modules/@vitejs/plugin-react-swc": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.11.0.tgz", - "integrity": "sha512-YTJCGFdNMHCMfjODYtxRNVAYmTWQ1Lb8PulP/2/f/oEEtglw8oKxKIZmmRkyXrVrHfsKOaVkAc3NT9/dMutO5w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rolldown/pluginutils": "1.0.0-beta.27", - "@swc/core": "^1.12.11" - }, - "peerDependencies": { - "vite": "^4 || ^5 || ^6 || ^7" - } - }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", @@ -3555,7 +3247,6 @@ "version": "1.0.30001727", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz", "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==", - "dev": true, "funding": [ { "type": "opencollective", @@ -3700,6 +3391,12 @@ "url": "https://polar.sh/cva" } }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://package-mirror.liara.ir/repository/npm/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -3999,6 +3696,16 @@ "node": ">=6" } }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://package-mirror.liara.ir/repository/npm/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/detect-node-es": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", @@ -4103,45 +3810,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -4342,16 +4010,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -4909,14 +4567,6 @@ "node": ">=12" } }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dependencies": { - "loose-envify": "^1.0.0" - } - }, "node_modules/is-alphabetical": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", @@ -5225,456 +4875,6 @@ "loose-envify": "cli.js" } }, - "node_modules/lovable-tagger": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/lovable-tagger/-/lovable-tagger-1.1.10.tgz", - "integrity": "sha512-LbYaxi6vgrqg7Sq93/cRbIM78EP+X+GUU7spx804yqB2bxfiOej8UvcZHeE4WqMjAFI2dHGhXpy8r6SnvmrzGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.25.9", - "@babel/types": "^7.25.8", - "esbuild": "^0.25.0", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.12", - "tailwindcss": "^3.4.17" - }, - "peerDependencies": { - "vite": ">=5.0.0 <8.0.0" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/aix-ppc64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", - "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/android-arm": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", - "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/android-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", - "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/android-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", - "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/darwin-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", - "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/darwin-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", - "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", - "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/freebsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", - "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/linux-arm": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", - "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/linux-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", - "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/linux-ia32": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", - "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/linux-loong64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", - "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/linux-mips64el": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", - "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/linux-ppc64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", - "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/linux-riscv64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", - "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/linux-s390x": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", - "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/linux-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz", - "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/netbsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", - "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/openbsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", - "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/sunos-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", - "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/win32-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", - "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/win32-ia32": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", - "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/@esbuild/win32-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", - "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/lovable-tagger/node_modules/esbuild": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", - "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.0", - "@esbuild/android-arm": "0.25.0", - "@esbuild/android-arm64": "0.25.0", - "@esbuild/android-x64": "0.25.0", - "@esbuild/darwin-arm64": "0.25.0", - "@esbuild/darwin-x64": "0.25.0", - "@esbuild/freebsd-arm64": "0.25.0", - "@esbuild/freebsd-x64": "0.25.0", - "@esbuild/linux-arm": "0.25.0", - "@esbuild/linux-arm64": "0.25.0", - "@esbuild/linux-ia32": "0.25.0", - "@esbuild/linux-loong64": "0.25.0", - "@esbuild/linux-mips64el": "0.25.0", - "@esbuild/linux-ppc64": "0.25.0", - "@esbuild/linux-riscv64": "0.25.0", - "@esbuild/linux-s390x": "0.25.0", - "@esbuild/linux-x64": "0.25.0", - "@esbuild/netbsd-arm64": "0.25.0", - "@esbuild/netbsd-x64": "0.25.0", - "@esbuild/openbsd-arm64": "0.25.0", - "@esbuild/openbsd-x64": "0.25.0", - "@esbuild/sunos-x64": "0.25.0", - "@esbuild/win32-arm64": "0.25.0", - "@esbuild/win32-ia32": "0.25.0", - "@esbuild/win32-x64": "0.25.0" - } - }, "node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", @@ -5689,16 +4889,6 @@ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" } }, - "node_modules/magic-string": { - "version": "0.30.12", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", - "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, "node_modules/markdown-table": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", @@ -6595,6 +5785,58 @@ "dev": true, "license": "MIT" }, + "node_modules/next": { + "version": "15.5.18", + "resolved": "https://package-mirror.liara.ir/repository/npm/next/-/next-15.5.18.tgz", + "integrity": "sha512-eKL8zUJkX9Y5lE+RX/2YJoItVdGlIscyVyboeD9wSpp0PaGqjoA4tTpT2qPqz9ax+5IzGESyLSeZ/RCwbSZ2uQ==", + "license": "MIT", + "dependencies": { + "@next/env": "15.5.18", + "@swc/helpers": "0.5.15", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "15.5.18", + "@next/swc-darwin-x64": "15.5.18", + "@next/swc-linux-arm64-gnu": "15.5.18", + "@next/swc-linux-arm64-musl": "15.5.18", + "@next/swc-linux-x64-gnu": "15.5.18", + "@next/swc-linux-x64-musl": "15.5.18", + "@next/swc-win32-arm64-msvc": "15.5.18", + "@next/swc-win32-x64-msvc": "15.5.18", + "sharp": "^0.34.3" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, "node_modules/next-themes": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.3.0.tgz", @@ -6605,6 +5847,43 @@ "react-dom": "^16.8 || ^17 || ^18" } }, + "node_modules/next/node_modules/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://package-mirror.liara.ir/repository/npm/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://package-mirror.liara.ir/repository/npm/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", @@ -7097,24 +6376,6 @@ "react": "^18.3.1" } }, - "node_modules/react-fast-compare": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", - "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" - }, - "node_modules/react-helmet-async": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-2.0.5.tgz", - "integrity": "sha512-rYUYHeus+i27MvFE+Jaa4WsyBKGkL6qVgbJvSBoX8mbsWoABJXdEO0bZyi0F6i+4f0NuIb8AvqPMj3iXFHkMwg==", - "dependencies": { - "invariant": "^2.2.4", - "react-fast-compare": "^3.2.2", - "shallowequal": "^1.1.0" - }, - "peerDependencies": { - "react": "^16.6.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/react-hook-form": { "version": "7.61.1", "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.61.1.tgz", @@ -7232,38 +6493,6 @@ "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, - "node_modules/react-router": { - "version": "6.30.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.1.tgz", - "integrity": "sha512-X1m21aEmxGXqENEPG3T6u0Th7g0aS4ZmoNynhbs+Cn+q+QGTLt+d5IQ2bHAXKzKcxGJjxACpVbnYQSCRcfxHlQ==", - "license": "MIT", - "dependencies": { - "@remix-run/router": "1.23.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8" - } - }, - "node_modules/react-router-dom": { - "version": "6.30.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.1.tgz", - "integrity": "sha512-llKsgOkZdbPU1Eg3zK8lCn+sjD9wMRZZPuzmdWWX5SUs8OFkN5HnFVC0u5KMeMaC9aoancFI/KoLuKPqN+hxHw==", - "license": "MIT", - "dependencies": { - "@remix-run/router": "1.23.0", - "react-router": "6.30.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" - } - }, "node_modules/react-smooth": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz", @@ -7511,42 +6740,6 @@ "node": ">= 0.8.15" } }, - "node_modules/rollup": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", - "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.6" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.24.0", - "@rollup/rollup-android-arm64": "4.24.0", - "@rollup/rollup-darwin-arm64": "4.24.0", - "@rollup/rollup-darwin-x64": "4.24.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", - "@rollup/rollup-linux-arm-musleabihf": "4.24.0", - "@rollup/rollup-linux-arm64-gnu": "4.24.0", - "@rollup/rollup-linux-arm64-musl": "4.24.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", - "@rollup/rollup-linux-riscv64-gnu": "4.24.0", - "@rollup/rollup-linux-s390x-gnu": "4.24.0", - "@rollup/rollup-linux-x64-gnu": "4.24.0", - "@rollup/rollup-linux-x64-musl": "4.24.0", - "@rollup/rollup-win32-arm64-msvc": "4.24.0", - "@rollup/rollup-win32-ia32-msvc": "4.24.0", - "@rollup/rollup-win32-x64-msvc": "4.24.0", - "fsevents": "~2.3.2" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -7580,10 +6773,10 @@ } }, "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, + "version": "7.8.0", + "resolved": "https://package-mirror.liara.ir/repository/npm/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "devOptional": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -7592,10 +6785,50 @@ "node": ">=10" } }, - "node_modules/shallowequal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", - "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://package-mirror.liara.ir/repository/npm/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } }, "node_modules/shebang-command": { "version": "2.0.0", @@ -7805,6 +7038,29 @@ "inline-style-parser": "0.2.4" } }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://package-mirror.liara.ir/repository/npm/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -8327,66 +7583,6 @@ "d3-timer": "^3.0.1" } }, - "node_modules/vite": { - "version": "5.4.19", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", - "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, "node_modules/web-namespaces": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", diff --git a/package.json b/package.json index 19325c1..a574077 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,13 @@ { - "name": "vite_react_shadcn_ts", + "name": "guilan-ace-frontend", "private": true, "version": "0.0.0", "type": "module", "scripts": { - "dev": "vite", - "build": "vite build", - "build:dev": "vite build --mode development", + "dev": "next dev --port 8080", + "build": "next build", "lint": "eslint .", - "preview": "vite preview" + "start": "next start --port 3000" }, "dependencies": { "@hookform/resolvers": "^3.10.0", @@ -45,17 +44,19 @@ "cmdk": "^1.1.1", "date-fns": "^3.6.0", "embla-carousel-react": "^8.6.0", + "html2canvas": "^1.4.1", "input-otp": "^1.4.2", + "jspdf": "^2.5.1", "lucide-react": "^0.462.0", + "next": "^15.4.6", "next-themes": "^0.3.0", "react": "^18.3.1", "react-day-picker": "^8.10.1", "react-dom": "^18.3.1", - "react-helmet-async": "^2.0.5", "react-hook-form": "^7.61.1", "react-markdown": "^9.0.3", + "react-qr-code": "^2.0.11", "react-resizable-panels": "^2.1.9", - "react-router-dom": "^6.30.1", "recharts": "^2.15.4", "rehype-raw": "^7.0.0", "rehype-sanitize": "^6.0.0", @@ -64,28 +65,23 @@ "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7", "vaul": "^0.9.9", - "zod": "^3.25.76", - "react-qr-code": "^2.0.11", - "jspdf": "^2.5.1", - "html2canvas": "^1.4.1" + "zod": "^3.25.76" }, "devDependencies": { "@eslint/js": "^9.32.0", + "@next/eslint-plugin-next": "^16.2.6", "@tailwindcss/typography": "^0.5.16", "@types/node": "^22.16.5", "@types/react": "^18.3.26", "@types/react-dom": "^18.3.7", - "@vitejs/plugin-react-swc": "^3.11.0", "autoprefixer": "^10.4.21", "eslint": "^9.32.0", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", "globals": "^15.15.0", - "lovable-tagger": "^1.1.10", "postcss": "^8.5.6", "tailwindcss": "^3.4.17", "typescript": "^5.8.3", - "typescript-eslint": "^8.38.0", - "vite": "^5.4.19" + "typescript-eslint": "^8.38.0" } } diff --git a/public/robots.txt b/public/robots.txt deleted file mode 100644 index 6018e70..0000000 --- a/public/robots.txt +++ /dev/null @@ -1,14 +0,0 @@ -User-agent: Googlebot -Allow: / - -User-agent: Bingbot -Allow: / - -User-agent: Twitterbot -Allow: / - -User-agent: facebookexternalhit -Allow: / - -User-agent: * -Allow: / diff --git a/src/App.tsx b/src/App.tsx deleted file mode 100644 index 0194362..0000000 --- a/src/App.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { Toaster } from "@/components/ui/toaster"; -import { Toaster as Sonner } from "@/components/ui/sonner"; -import { TooltipProvider } from "@/components/ui/tooltip"; -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { HelmetProvider } from "react-helmet-async"; -import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom"; -import Layout from "@/components/Layout"; -import { AuthProvider } from "@/contexts/AuthContext"; -import AdminLayout from "@/pages/AdminLayout"; -import AdminUsers from "@/pages/AdminUsers"; -import AdminEvents from "@/pages/AdminEvents"; -import AdminEventEdit from "@/pages/AdminEventEdit"; -import AdminEventDetail from "@/pages/AdminEventDetail"; -import AboutUs from "@/pages/AboutUs"; -import Auth from "@/pages/Auth"; -import Blog from "@/pages/Blog"; -import EventDetail from "@/pages/EventDetail"; -import EventFreeSuccessPage from "@/pages/EventFreeSuccessPage"; -import Events from "@/pages/Events"; -import Home from "@/pages/Home"; -import Logout from "@/pages/Logout"; -import NotFound from "@/pages/NotFound"; -import PaymentResult from "@/pages/PaymentResult"; -import Profile from "@/pages/Profile"; -import ResetPasswordConfirm from "@/pages/ResetPasswordConfirm"; -import ResetPasswordRequest from "@/pages/ResetPasswordRequest"; -import VerifyEmail from "@/pages/VerifyEmail"; - -const queryClient = new QueryClient(); - -const App = () => ( - - - - - - - - - }> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - }> - } /> - } /> - } /> - } /> - } /> - - - - } /> - - - - - - -); - -export default App; diff --git a/src/app/about/page.tsx b/src/app/about/page.tsx new file mode 100644 index 0000000..e200ba5 --- /dev/null +++ b/src/app/about/page.tsx @@ -0,0 +1,65 @@ +import type { Metadata } from "next"; +import AboutUs from "@/views/AboutUs"; +import { siteUrl } from "@/lib/site"; + +const title = "درباره ما | انجمن علمی کامپیوتر شرق گیلان"; +const description = + "آشنایی با تاریخچه، مأموریت‌ها و دستاوردهای انجمن علمی کامپیوتر شرق گیلان و راه‌های مشارکت دانشجویان در برنامه‌های انجمن."; + +export const metadata: Metadata = { + title, + description, + keywords: [ + "انجمن علمی کامپیوتر شرق گیلان", + "دانشگاه گیلان", + "انجمن علمی دانشجویی", + "رویدادهای فناوری", + ], + alternates: { canonical: "/about" }, + openGraph: { + title, + description, + url: `${siteUrl}/about`, + siteName: "انجمن علمی کامپیوتر شرق گیلان", + type: "website", + images: [`${siteUrl}/favicon.ico`], + locale: "fa_IR", + }, + twitter: { + card: "summary_large_image", + title, + description, + images: [`${siteUrl}/favicon.ico`], + }, +}; + +const structuredData = { + "@context": "https://schema.org", + "@type": "AboutPage", + name: title, + description, + url: `${siteUrl}/about`, + mainEntity: { + "@type": "Organization", + name: "انجمن علمی کامپیوتر شرق گیلان", + url: siteUrl, + logo: `${siteUrl}/favicon.ico`, + sameAs: [ + "https://instagram.com/guilance.ir", + "https://t.me/guilance", + "https://t.me/guilancea", + ], + }, +}; + +export default function AboutPage() { + return ( + <> + - )} - - -
-
-

رویدادها

- -
- setSearch(e.target.value)} - className="max-w-md" - /> -
- - {loading ? ( -

در حال بارگذاری...

- ) : events.length === 0 ? ( -

رویدادی یافت نشد

- ) : ( -
- {events.map((event) => ( - - -
- {event.title} -
- - {/* این رپر حالا قدِ باقی‌مانده رو می‌گیره */} -
- -
- {event.title} - {modeFa(event.event_type)} -
- {formatJalali(event.start_time, false)} -
- - -
-
- ظرفیت رویداد - - {formatNumberPersian(Number(event?.capacity ?? 0) - Number(event?.registration_count ?? 0))}/{formatNumberPersian(Number(event?.capacity ?? 0))} نفر - -
-
- هزینه‌ی ثبت‌نام - {labelPrice(event)} -
- {isAvailable(event) ? ( - - ) : ( - - )} -
-
-
-
- - ))} -
- )} -
-
- - ); -} diff --git a/src/pages/Index.tsx b/src/pages/Index.tsx deleted file mode 100644 index 7130b54..0000000 --- a/src/pages/Index.tsx +++ /dev/null @@ -1,14 +0,0 @@ -// Update this page (the content is just a fallback if you fail to update the page) - -const Index = () => { - return ( -
-
-

Welcome to Your Blank App

-

Start building your amazing project here!

-
-
- ); -}; - -export default Index; diff --git a/src/pages/NotFound.tsx b/src/pages/NotFound.tsx deleted file mode 100644 index 34fc289..0000000 --- a/src/pages/NotFound.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { useLocation } from "react-router-dom"; -import { useEffect } from "react"; -import { toPersianDigits } from "@/lib/utils"; - -const NotFound = () => { - const location = useLocation(); - - useEffect(() => { - console.error("404 Error: User attempted to access non-existent route:", location.pathname); - }, [location.pathname]); - - return ( -
- ); -}; - -export default NotFound; diff --git a/src/pages/AboutUs.tsx b/src/views/AboutUs.tsx similarity index 99% rename from src/pages/AboutUs.tsx rename to src/views/AboutUs.tsx index 53959cc..0cac8fb 100644 --- a/src/pages/AboutUs.tsx +++ b/src/views/AboutUs.tsx @@ -1,7 +1,7 @@ import React from 'react'; -import { Helmet } from 'react-helmet-async'; -import { Link } from 'react-router-dom'; +import { Helmet } from '@/lib/helmet'; +import { Link } from '@/lib/router'; // ------ داده‌های قابل تنظیم ------ const SITE_URL = 'https://east-guilan-ce.ir'; diff --git a/src/pages/AdminEventDetail.tsx b/src/views/AdminEventDetail.tsx similarity index 99% rename from src/pages/AdminEventDetail.tsx rename to src/views/AdminEventDetail.tsx index 143eb1f..48ca146 100644 --- a/src/pages/AdminEventDetail.tsx +++ b/src/views/AdminEventDetail.tsx @@ -1,5 +1,7 @@ +"use client"; + import * as React from 'react'; -import { useParams, Link, Navigate } from 'react-router-dom'; +import { useParams, Link, Navigate } from '@/lib/router'; import { useQuery } from '@tanstack/react-query'; import { api } from '@/lib/api'; import { Badge } from '@/components/ui/badge'; diff --git a/src/pages/AdminEventEdit.tsx b/src/views/AdminEventEdit.tsx similarity index 92% rename from src/pages/AdminEventEdit.tsx rename to src/views/AdminEventEdit.tsx index 8c978f5..a520673 100644 --- a/src/pages/AdminEventEdit.tsx +++ b/src/views/AdminEventEdit.tsx @@ -1,5 +1,7 @@ +"use client"; + import * as React from 'react'; -import { useNavigate, useParams, Navigate } from 'react-router-dom'; +import { useNavigate, useParams, Navigate } from '@/lib/router'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useAuth } from '@/contexts/AuthContext'; import { api } from '@/lib/api'; @@ -42,6 +44,7 @@ export default function AdminEventEdit() { const navigate = useNavigate(); const eventId = Number(id); const { toast } = useToast(); + const queryClient = useQueryClient(); const detailQuery = useQuery({ queryKey: ['admin', 'edit-event', eventId], @@ -51,8 +54,8 @@ export default function AdminEventEdit() { const [formData, setFormData] = React.useState({ title: '', - status: 'draft', - event_type: 'online', + status: 'draft' as NonNullable, + event_type: 'online' as NonNullable, price: '', capacity: '', start_time: '', @@ -147,7 +150,7 @@ export default function AdminEventEdit() { event_type: formData.event_type, price: formData.price ? Number(formData.price) * 10 : 0, capacity: formData.capacity ? Number(formData.capacity) : null, - start_time: formData.start_time || null, + start_time: formData.start_time || undefined, end_time: formData.end_time || null, registration_start_date: formData.registration_start_date || null, registration_end_date: formData.registration_end_date || null, @@ -167,7 +170,12 @@ export default function AdminEventEdit() { /> setFilters((prev) => ({ ...prev, status: value }))}> + - + setFilters((prev) => ({ + ...prev, + type: value as 'all' | EventListItemSchema['event_type'], + })) + } + > {{ @@ -144,7 +168,15 @@ const AdminEventsPage: React.FC = () => { ترکیبی - + setFilters((prev) => ({ + ...prev, + sort: value as (typeof eventSortOptions)[number]['value'], + })) + } + > {eventSortOptions.find((option) => option.value === filters.sort)?.label || diff --git a/src/pages/AdminLayout.tsx b/src/views/AdminLayout.tsx similarity index 86% rename from src/pages/AdminLayout.tsx rename to src/views/AdminLayout.tsx index a51bb29..7a43b23 100644 --- a/src/pages/AdminLayout.tsx +++ b/src/views/AdminLayout.tsx @@ -1,4 +1,7 @@ -import { Outlet, Navigate, NavLink, useLocation } from 'react-router-dom'; +"use client"; + +import type { ReactNode } from 'react'; +import { Navigate, NavLink, useLocation } from '@/lib/router'; import { useMemo } from 'react'; import { useAuth } from '@/contexts/AuthContext'; @@ -7,7 +10,7 @@ const navItems = [ { to: '/admin/events', label: 'مدیریت رویدادها' }, ] as const; -export default function AdminLayout() { +export default function AdminLayout({ children }: { children: ReactNode }) { const location = useLocation(); const { user, isAuthenticated, loading } = useAuth(); const isAdmin = useMemo( @@ -40,7 +43,7 @@ export default function AdminLayout() { className={({ isActive }) => [ 'rounded-full px-4 py-2 text-sm transition', - (isActive || location.pathname.startsWith(item.to)) + (isActive || location.pathname?.startsWith(item.to)) ? 'bg-primary text-primary-foreground shadow' : 'bg-card text-muted-foreground hover:text-foreground border', ].join(' ') @@ -53,7 +56,7 @@ export default function AdminLayout() {
- + {children}
); diff --git a/src/pages/AdminUsers.tsx b/src/views/AdminUsers.tsx similarity index 99% rename from src/pages/AdminUsers.tsx rename to src/views/AdminUsers.tsx index c01a240..c500f09 100644 --- a/src/pages/AdminUsers.tsx +++ b/src/views/AdminUsers.tsx @@ -1,3 +1,5 @@ +"use client"; + import * as React from 'react'; import { useQuery, diff --git a/src/pages/Auth.tsx b/src/views/Auth.tsx similarity index 99% rename from src/pages/Auth.tsx rename to src/views/Auth.tsx index 751b74f..fede829 100644 --- a/src/pages/Auth.tsx +++ b/src/views/Auth.tsx @@ -1,6 +1,8 @@ +"use client"; + import { useEffect, useState, useMemo } from 'react'; -import { Helmet } from 'react-helmet-async'; -import { Link, useNavigate } from 'react-router-dom'; +import { Helmet } from '@/lib/helmet'; +import { Link, useNavigate } from '@/lib/router'; import { useAuth } from '@/contexts/AuthContext'; import { useQuery } from '@tanstack/react-query'; import { Button } from '@/components/ui/button'; diff --git a/src/pages/Blog.tsx b/src/views/Blog.tsx similarity index 62% rename from src/pages/Blog.tsx rename to src/views/Blog.tsx index 82b1643..4256d3a 100644 --- a/src/pages/Blog.tsx +++ b/src/views/Blog.tsx @@ -1,36 +1,42 @@ -import { useEffect, useState, useCallback } from 'react'; -import { Link } from 'react-router-dom'; -import { api } from '@/lib/api'; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; -import { Input } from '@/components/ui/input'; +"use client"; -interface Post { - id: number; - title: string; - slug: string; - excerpt?: string; - author: { - username: string; - first_name: string; - last_name: string; - }; - created_at: string; - category?: { - name: string; - }; -} +import { useCallback, useEffect, useState } from "react"; +import { Link, useLocation, useNavigate } from "@/lib/router"; +import { api } from "@/lib/api"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; +import type * as Types from "@/lib/types"; -export default function Blog() { - const [posts, setPosts] = useState([]); - const [search, setSearch] = useState(''); - const [loading, setLoading] = useState(true); +type BlogProps = { + initialPosts?: Types.PostListSchema[]; + initialSearch?: string; +}; + +export default function Blog({ + initialPosts = [], + initialSearch = "", +}: BlogProps) { + const navigate = useNavigate(); + const location = useLocation(); + const [posts, setPosts] = useState(initialPosts); + const [search, setSearch] = useState(initialSearch); + const [loading, setLoading] = useState(!initialPosts.length && !initialSearch); + + useEffect(() => { + setPosts(initialPosts); + }, [initialPosts]); + + useEffect(() => { + setSearch(initialSearch); + }, [initialSearch]); const loadPosts = useCallback(async () => { try { + setLoading(true); const data = await api.getPosts({ search: search || undefined }); - setPosts(data as Post[]); + setPosts(data); } catch (error) { - console.error('Error loading posts:', error); + console.error("Error loading posts:", error); } finally { setLoading(false); } @@ -40,6 +46,18 @@ export default function Blog() { loadPosts(); }, [loadPosts]); + useEffect(() => { + const params = new URLSearchParams(); + if (search.trim()) { + params.set("search", search.trim()); + } + const basePath = location.pathname || "/blog"; + const nextPath = params.size + ? `${basePath}?${params.toString()}` + : basePath; + navigate(nextPath, { replace: true }); + }, [location.pathname, navigate, search]); + return (
@@ -70,7 +88,7 @@ export default function Blog() { {post.category?.name && ( {post.category.name} )} - {new Date(post.created_at).toLocaleDateString('fa-IR')} + {new Date(post.created_at).toLocaleDateString("fa-IR")} diff --git a/src/pages/EventDetail.tsx b/src/views/EventDetail.tsx similarity index 53% rename from src/pages/EventDetail.tsx rename to src/views/EventDetail.tsx index e1b672c..be19a93 100644 --- a/src/pages/EventDetail.tsx +++ b/src/views/EventDetail.tsx @@ -1,43 +1,86 @@ -import { useEffect, useMemo, useState } from 'react'; -import { Helmet } from 'react-helmet-async'; -import { useParams, useNavigate } from 'react-router-dom'; -import { api } from '@/lib/api'; -import type * as Types from '@/lib/types'; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; -import { Badge } from '@/components/ui/badge'; -import { Button } from '@/components/ui/button'; -import { useToast } from '@/hooks/use-toast'; -import Markdown from '@/components/Markdown'; -import CouponDialogFa from '@/components/CouponDialogFa'; -import { formatJalali, formatNumberPersian, formatToman, getThumbUrl, resolveErrorMessage, toPersianDigits } from '@/lib/utils'; -import { useAuth } from '@/contexts/AuthContext'; +"use client"; -const typeLabel: Record = { online: 'آنلاین', on_site: 'حضوری', hybrid: 'آنلاین و حضوری' }; +import { useEffect, useMemo, useState } from "react"; +import { Helmet } from "@/lib/helmet"; +import { useNavigate, useParams } from "@/lib/router"; +import { api } from "@/lib/api"; +import type * as Types from "@/lib/types"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { useToast } from "@/hooks/use-toast"; +import Markdown from "@/components/Markdown"; +import CouponDialogFa from "@/components/CouponDialogFa"; +import { + formatJalali, + formatNumberPersian, + formatToman, + getThumbUrl, + resolveErrorMessage, + toPersianDigits, +} from "@/lib/utils"; +import { useAuth } from "@/contexts/AuthContext"; +import { siteUrl } from "@/lib/site"; -export default function EventDetail() { +const typeLabel: Record = { + online: "آنلاین", + on_site: "حضوری", + hybrid: "آنلاین و حضوری", +}; + +type EventDetailProps = { + initialEvent?: Types.EventDetailSchema | null; +}; + +function buildPaymentSnapshot( + event: Types.EventDetailSchema, + eventThumb: string | null, + payload: { + baseAmount: number; + discountAmount: number; + amount: number; + }, +) { + return JSON.stringify({ + event_id: event.id, + slug: event.slug, + title: event.title, + thumb: eventThumb, + base_amount: payload.baseAmount, + discount_amount: payload.discountAmount, + amount: payload.amount, + started_at: new Date().toISOString(), + success_markdown: event.registration_success_markdown, + }); +} + +export default function EventDetail({ initialEvent = null }: EventDetailProps) { const { slug } = useParams<{ slug: string }>(); const { isAuthenticated } = useAuth(); const navigate = useNavigate(); const { toast } = useToast(); - const [event, setEvent] = useState(null); - const [eventThumb, setEventThumb] = useState(null); - const [loading, setLoading] = useState(true); + const [event, setEvent] = useState(initialEvent); + const [eventThumb, setEventThumb] = useState( + initialEvent ? getThumbUrl(initialEvent) : null, + ); + const [loading, setLoading] = useState(!initialEvent); + const [open, setOpen] = useState(false); + const [submitting, setSubmitting] = useState(false); + const [alreadyRegistered, setAlreadyRegistered] = useState(false); + const [nowTs, setNowTs] = useState(() => Date.now()); const basePrice = Number(event?.price ?? 0); const isFree = useMemo(() => basePrice <= 0, [basePrice]); - const [open, setOpen] = useState(false); - const [submitting, setSubmitting] = useState(false); - const siteUrl = 'https://east-guilan-ce.ir'; - const siteName = 'انجمن علمی کامپیوتر شرق گیلان'; + const siteName = "انجمن علمی کامپیوتر شرق گیلان"; const defaultDescription = - 'جزئیات کامل رویدادهای انجمن علمی کامپیوتر شرق گیلان شامل زمان، مکان و شرایط ثبت‌نام.'; + "جزئیات کامل رویدادهای انجمن علمی کامپیوتر شرق گیلان شامل زمان، مکان و شرایط ثبت‌نام."; - const toAbsoluteUrl = (url?: string | null) => { - if (!url) return undefined; - if (url.startsWith('http')) return url; - const normalizedSite = siteUrl.endsWith('/') ? siteUrl.slice(0, -1) : siteUrl; - const normalizedPath = url.startsWith('/') ? url.slice(1) : url; + const toAbsoluteUrl = (value?: string | null) => { + if (!value) return undefined; + if (value.startsWith("http")) return value; + const normalizedSite = siteUrl.endsWith("/") ? siteUrl.slice(0, -1) : siteUrl; + const normalizedPath = value.startsWith("/") ? value.slice(1) : value; return `${normalizedSite}/${normalizedPath}`; }; @@ -55,185 +98,215 @@ export default function EventDetail() { : `${siteUrl}/favicon.ico`; const pageTitle = event ? `${event.title} | ${siteName}` : `جزئیات رویداد | ${siteName}`; const pageDescription = sanitizeDescription(event?.description); - const pageRobots = event?.status === 'draft' ? 'noindex, nofollow' : 'index, follow'; - - const [alreadyRegistered, setAlreadyRegistered] = useState(false); + const pageRobots = event?.status === "draft" ? "noindex, nofollow" : "index, follow"; useEffect(() => { let cancelled = false; - async function check() { - if (isAuthenticated && event?.id) { - try { - const res = await api.getRegistrationStatus(event.id); - if (!cancelled) setAlreadyRegistered(res.is_registered); - } catch { /* ignore */ } + + async function checkRegistration() { + if (!isAuthenticated || !event?.id) { + return; + } + + try { + const res = await api.getRegistrationStatus(event.id); + if (!cancelled) { + setAlreadyRegistered(res.is_registered); + } + } catch { + // Ignore registration status failures on the detail page. } } - check(); - return () => { cancelled = true; }; - }, [isAuthenticated, event?.id]); + + checkRegistration(); + return () => { + cancelled = true; + }; + }, [event?.id, isAuthenticated]); const goSuccess = (registrationId?: string) => { - const q = registrationId ? `?registration_id=${registrationId}` : ''; + if (!event) return; + const query = registrationId ? `?registration_id=${registrationId}` : ""; setAlreadyRegistered(true); - - toast({ title: 'ثبت‌نام با موفقیت انجام شد!', variant: 'success' }); - navigate(`/events/${event!.slug}/success${q}`); + toast({ title: "ثبت‌نام با موفقیت انجام شد!", variant: "success" }); + navigate(`/events/${event.slug}/success${query}`); }; const handleMainCTA = async () => { if (!event) return; + if (!isAuthenticated) { - toast({ title: 'ابتدا وارد شوید', description: 'برای ثبت‌نام در رویداد باید وارد حساب کاربری خود شوید.', variant: 'destructive' }); - navigate('/auth'); + toast({ + title: "ابتدا وارد شوید", + description: "برای ثبت‌نام در رویداد باید وارد حساب کاربری خود شوید.", + variant: "destructive", + }); + navigate("/auth"); return; } - if (isFree) { - try { - setSubmitting(true); - const res = await api.registerForEvent(event.id); - goSuccess(res.ticket_id); - } catch (error: unknown) { - const msg = resolveErrorMessage(error, ''); - if (msg.includes('already registered') || msg.includes('ثبت‌نام')) { - setAlreadyRegistered(true); - toast({ title: 'شما قبلاً ثبت‌نام کرده‌اید', variant: 'destructive' }); - return; - } - throw error; - } finally { - setSubmitting(false); - } - } else { - setOpen(true); - } - }; - const handleContinueFromModal = async (coupon?: string, finalAmount?: number) => { - if (!event) return; - if (!isAuthenticated) { - toast({ title: 'ابتدا وارد شوید', description: 'برای ثبت‌نام در رویداد باید وارد حساب کاربری خود شوید.', variant: 'destructive' }); - navigate('/auth'); + if (!isFree) { + setOpen(true); return; } try { setSubmitting(true); + const res = await api.registerForEvent(event.id); + goSuccess(res.ticket_id); + } catch (error: unknown) { + const msg = resolveErrorMessage(error, ""); + if (msg.includes("already registered")) { + setAlreadyRegistered(true); + toast({ title: "شما قبلاً ثبت‌نام کرده‌اید", variant: "destructive" }); + return; + } + toast({ + title: "خطا در ثبت‌نام", + description: msg || "لطفاً دوباره تلاش کنید.", + variant: "destructive", + }); + } finally { + setSubmitting(false); + } + }; + const handleContinueFromModal = async (coupon?: string, finalAmount?: number) => { + if (!event) return; + + if (!isAuthenticated) { + toast({ + title: "ابتدا وارد شوید", + description: "برای ثبت‌نام در رویداد باید وارد حساب کاربری خود شوید.", + variant: "destructive", + }); + navigate("/auth"); + return; + } + + try { + setSubmitting(true); const reg = await api.registerForEvent(event.id, coupon); - - if (finalAmount === 0) { - sessionStorage.setItem('payment:last', JSON.stringify({ - event_id: event.id, - slug: event.slug, - title: event.title, - thumb: eventThumb, - base_amount: Number(event.price ?? 0), - discount_amount: Number(event.price ?? 0), - amount: 0, - started_at: new Date().toISOString(), - success_markdown: event.registration_success_markdown, - })); - api.ChangeRegistrationStatus(reg.id, 'confirmed') - goSuccess(reg?.ticket_id); - return; + if (finalAmount === 0) { + window.sessionStorage.setItem( + "payment:last", + buildPaymentSnapshot(event, eventThumb, { + baseAmount: Number(event.price ?? 0), + discountAmount: Number(event.price ?? 0), + amount: 0, + }), + ); + await api.ChangeRegistrationStatus(reg.id, "confirmed"); + goSuccess(reg.ticket_id); + return; } - const description = `پرداخت رویداد: ${event.title}`; const result = await api.createPayment({ event_id: event.id, - description, - discount_code: (coupon ?? '').trim() || null, + description: `پرداخت رویداد: ${event.title}`, + discount_code: (coupon ?? "").trim() || null, }); - if (!result?.start_pay_url || Number(result.amount) === 0) { - sessionStorage.setItem('payment:last', JSON.stringify({ - event_id: event.id, - slug: event.slug, - title: event.title, - thumb: eventThumb, - base_amount: result.base_amount, - discount_amount: result.discount_amount ?? result.base_amount, - amount: 0, - started_at: new Date().toISOString(), - success_markdown: event.registration_success_markdown, - })); - goSuccess(reg?.ticket_id); + window.sessionStorage.setItem( + "payment:last", + buildPaymentSnapshot(event, eventThumb, { + baseAmount: result.base_amount, + discountAmount: result.discount_amount ?? result.base_amount, + amount: 0, + }), + ); + goSuccess(reg.ticket_id); return; } - - sessionStorage.setItem('payment:last', JSON.stringify({ - event_id: event.id, - slug: event.slug, - title: event.title, - thumb: eventThumb, - base_amount: result.base_amount, - discount_amount: result.discount_amount, - amount: result.amount, - started_at: new Date().toISOString(), - success_markdown: event.registration_success_markdown, - })); + window.sessionStorage.setItem( + "payment:last", + buildPaymentSnapshot(event, eventThumb, { + baseAmount: result.base_amount, + discountAmount: result.discount_amount, + amount: result.amount, + }), + ); window.location.href = result.start_pay_url; - } catch (error: unknown) { - - const msg = resolveErrorMessage(error, ''); - if (msg.includes('already registered') || msg.includes('ثبت‌نام')) { + const msg = resolveErrorMessage(error, ""); + if (msg.includes("already registered")) { setAlreadyRegistered(true); - toast({ title: 'شما قبلاً ثبت‌نام کرده‌اید', variant: 'destructive' }); + toast({ title: "شما قبلاً ثبت‌نام کرده‌اید", variant: "destructive" }); return; } - toast({ title: 'خطا در پردازش پرداخت', description: msg || 'لطفاً دوباره تلاش کنید.', variant: 'destructive' }); + toast({ + title: "خطا در پردازش پرداخت", + description: msg || "لطفاً دوباره تلاش کنید.", + variant: "destructive", + }); } finally { setSubmitting(false); setOpen(false); } }; - useEffect(() => { - (async () => { + let cancelled = false; + + async function loadEvent() { try { if (!slug) return; + + if (initialEvent && initialEvent.slug === slug) { + setEvent(initialEvent); + setEventThumb(getThumbUrl(initialEvent)); + return; + } + const data = await api.getEventBySlug(slug); + if (cancelled) return; setEvent(data); setEventThumb(getThumbUrl(data)); } catch (error: unknown) { + if (cancelled) return; toast({ - title: 'خطا در بارگذاری رویداد', - description: resolveErrorMessage(error, 'لطفاً دوباره تلاش کنید.'), - variant: 'destructive', + title: "خطا در بارگذاری رویداد", + description: resolveErrorMessage(error, "لطفاً دوباره تلاش کنید."), + variant: "destructive", }); } finally { - setLoading(false); + if (!cancelled) { + setLoading(false); + } } - })(); - }, [slug, toast]); + } + + loadEvent(); + return () => { + cancelled = true; + }; + }, [initialEvent, slug, toast]); - - const [nowTs, setNowTs] = useState(() => Date.now()); useEffect(() => { - const id = window.setInterval(() => setNowTs(Date.now()), 1000); - return () => window.clearInterval(id); + const timer = window.setInterval(() => setNowTs(Date.now()), 1000); + return () => window.clearInterval(timer); }, []); - const rsTs = useMemo(() => ( - event?.registration_start_date ? new Date(event.registration_start_date).getTime() : null - ), [event?.registration_start_date]); + const rsTs = useMemo( + () => (event?.registration_start_date ? new Date(event.registration_start_date).getTime() : null), + [event?.registration_start_date], + ); - const deadlineTs = useMemo(() => ( - event?.registration_end_date ? new Date(event.registration_end_date).getTime() : null - ), [event?.registration_end_date]); + const deadlineTs = useMemo( + () => (event?.registration_end_date ? new Date(event.registration_end_date).getTime() : null), + [event?.registration_end_date], + ); - const remainingMs = useMemo(() => ( - deadlineTs != null ? Math.max(0, deadlineTs - nowTs) : null - ), [deadlineTs, nowTs]); + const remainingMs = useMemo( + () => (deadlineTs != null ? Math.max(0, deadlineTs - nowTs) : null), + [deadlineTs, nowTs], + ); const formatCountdownTwoDigit = (value: number) => - toPersianDigits(value.toString().padStart(2, '0')); + toPersianDigits(value.toString().padStart(2, "0")); const formatCountdownNumber = (value: number) => formatNumberPersian(value); const formatRemainingWords = (ms: number) => { @@ -242,39 +315,45 @@ export default function EventDetail() { const hours = Math.floor((total % 86400) / 3600); const minutes = Math.floor((total % 3600) / 60); const seconds = total % 60; - if (days === 0) return `${formatCountdownTwoDigit(hours)} ساعت و ${formatCountdownTwoDigit(minutes)} دقیقه و ${formatCountdownTwoDigit(seconds)} ثانیه`; + + if (days === 0) { + return `${formatCountdownTwoDigit(hours)} ساعت و ${formatCountdownTwoDigit(minutes)} دقیقه و ${formatCountdownTwoDigit(seconds)} ثانیه`; + } + return `${formatCountdownNumber(days)} روز و ${formatCountdownTwoDigit(hours)} ساعت و ${formatCountdownTwoDigit(minutes)} دقیقه و ${formatCountdownTwoDigit(seconds)} ثانیه`; }; const meta = useMemo(() => { if (!event) return null; - const rs = rsTs; - const re = deadlineTs; - const registrationOpen = (rs == null || nowTs >= rs) && (re == null || nowTs <= re); + const registrationOpen = + (rsTs == null || nowTs >= rsTs) && (deadlineTs == null || nowTs <= deadlineTs); const unlimited = event.capacity == null; - const remaining = unlimited ? Infinity : Math.max(0, (event.capacity || 0) - (event.registration_count || 0)); + const remaining = unlimited + ? Number.POSITIVE_INFINITY + : Math.max(0, (event.capacity || 0) - (event.registration_count || 0)); const full = !unlimited && remaining <= 0; return { registrationOpen, remaining, full }; - }, [event, rsTs, deadlineTs, nowTs]); + }, [deadlineTs, event, nowTs, rsTs]); + const eventStructuredData = useMemo(() => { if (!event) return null; const attendanceModeMap: Record = { - online: 'https://schema.org/OnlineEventAttendanceMode', - on_site: 'https://schema.org/OfflineEventAttendanceMode', - hybrid: 'https://schema.org/MixedEventAttendanceMode', + online: "https://schema.org/OnlineEventAttendanceMode", + on_site: "https://schema.org/OfflineEventAttendanceMode", + hybrid: "https://schema.org/MixedEventAttendanceMode", }; const statusMap: Record = { - published: 'https://schema.org/EventScheduled', - completed: 'https://schema.org/EventCompleted', - cancelled: 'https://schema.org/EventCancelled', - draft: 'https://schema.org/EventPostponed', + published: "https://schema.org/EventScheduled", + completed: "https://schema.org/EventCompleted", + cancelled: "https://schema.org/EventCancelled", + draft: "https://schema.org/EventPostponed", }; const data: Record = { - '@context': 'https://schema.org', - '@type': 'Event', + "@context": "https://schema.org", + "@type": "Event", name: event.title, description: pageDescription, startDate: event.start_time, @@ -282,7 +361,7 @@ export default function EventDetail() { eventAttendanceMode: attendanceModeMap[event.event_type] ?? attendanceModeMap.hybrid, eventStatus: statusMap[event.status] ?? statusMap.published, organizer: { - '@type': 'Organization', + "@type": "Organization", name: siteName, url: siteUrl, }, @@ -296,14 +375,14 @@ export default function EventDetail() { data.image = [primaryImage]; } - if (event.event_type === 'online') { + if (event.event_type === "online") { data.location = { - '@type': 'VirtualLocation', + "@type": "VirtualLocation", url: event.online_link || canonicalUrl, }; } else { const location: Record = { - '@type': 'Place', + "@type": "Place", name: event.location || event.address || siteName, }; if (event.address) { @@ -316,11 +395,11 @@ export default function EventDetail() { } const offers: Record = { - '@type': 'Offer', + "@type": "Offer", url: canonicalUrl, - priceCurrency: 'IRR', + priceCurrency: "IRR", price: String(event.price ?? 0), - availability: meta?.full ? 'https://schema.org/SoldOut' : 'https://schema.org/InStock', + availability: meta?.full ? "https://schema.org/SoldOut" : "https://schema.org/InStock", }; if (event.registration_start_date) { @@ -331,9 +410,8 @@ export default function EventDetail() { } data.offers = offers; - return data; - }, [event, pageDescription, canonicalUrl, primaryImage, meta?.full, siteName, siteUrl]); + }, [canonicalUrl, event, meta?.full, pageDescription, primaryImage, siteName]); const helmet = ( @@ -370,23 +448,26 @@ export default function EventDetail() { if (loading) { return withHelmet( -
در حال بارگذاری رویداد...
- ); - } - if (!event) { - return withHelmet( -
رویداد مورد نظر یافت نشد.
+
+ در حال بارگذاری رویداد... +
, + ); + } + + if (!event) { + return withHelmet( +
+ رویداد مورد نظر یافت نشد. +
, ); } - const beforeStart = rsTs != null && nowTs < rsTs; const ended = deadlineTs !== null && remainingMs === 0; - const showCountdown = !beforeStart && deadlineTs !== null && remainingMs! > 0; + const showCountdown = !beforeStart && deadlineTs !== null && (remainingMs ?? 0) > 0; return withHelmet(
- {/* --- نوار اطلاع/تایمر زیر نوار ناوبری با رنگ‌های مناسب Light/Dark --- */} {beforeStart && (
@@ -395,13 +476,13 @@ export default function EventDetail() {
)} - {showCountdown && ( + {showCountdown && remainingMs != null && (
زمان باقی‌مانده تا پایان ثبت‌نام: - {formatRemainingWords(remainingMs!)} + {formatRemainingWords(remainingMs)}
@@ -417,7 +498,6 @@ export default function EventDetail() { )}
- {/* محتوا */}
@@ -449,16 +529,15 @@ export default function EventDetail() { - {/* گالری */} {event.gallery_images?.length ? (

گالری تصاویر

- {event.gallery_images.map((g) => ( + {event.gallery_images.map((image) => ( {g.title ))} @@ -467,7 +546,6 @@ export default function EventDetail() { ) : null}
- {/* سایدبار اطلاعات */}
@@ -477,20 +555,18 @@ export default function EventDetail() { {event.address &&
آدرس: {event.address}
} - -
ظرفیت کل: {event.capacity == null ? 'نامحدود' : formatNumberPersian(event.capacity)}
- {meta && ( - <> - {!event.capacity ? null : ( -
- ظرفیت باقی‌مانده: {meta.remaining === Infinity ? 'نامحدود' : formatNumberPersian(meta.remaining)} -
- )} - +
+ ظرفیت کل: {event.capacity == null ? "نامحدود" : formatNumberPersian(event.capacity)} +
+ {meta && event.capacity != null && ( +
+ ظرفیت باقی‌مانده:{" "} + {meta.remaining === Number.POSITIVE_INFINITY + ? "نامحدود" + : formatNumberPersian(meta.remaining)} +
)} -
هزینه حضور: {event.price ? formatToman(event.price) : 'رایگان'}
- - {/* نمایش زمان شروع/پایان ثبت‌نام در UI حذف شده */} +
هزینه حضور: {event.price ? formatToman(event.price) : "رایگان"}
{!isFree && ( @@ -536,11 +611,3 @@ export default function EventDetail() {
); } - - - - - - - - diff --git a/src/pages/EventFreeSuccessPage.tsx b/src/views/EventFreeSuccessPage.tsx similarity index 98% rename from src/pages/EventFreeSuccessPage.tsx rename to src/views/EventFreeSuccessPage.tsx index e62e199..3264dd5 100644 --- a/src/pages/EventFreeSuccessPage.tsx +++ b/src/views/EventFreeSuccessPage.tsx @@ -1,11 +1,13 @@ -import { useLocation, useParams, Link } from "react-router-dom"; +"use client"; + +import { useLocation, useParams, Link } from "@/lib/router"; import { useQuery } from "@tanstack/react-query"; import { Button } from "@/components/ui/button"; import { api } from "@/lib/api"; import PaymentResult from "@/components/PaymentResult"; import { formatJalali } from "@/lib/utils"; import Markdown from '@/components/Markdown'; -import { Helmet } from "react-helmet-async"; +import { Helmet } from "@/lib/helmet"; export default function EventFreeSuccessPage() { const { slug } = useParams(); diff --git a/src/views/Events.tsx b/src/views/Events.tsx new file mode 100644 index 0000000..82a8b7c --- /dev/null +++ b/src/views/Events.tsx @@ -0,0 +1,262 @@ +"use client"; + +import { useCallback, useEffect, useMemo, useState } from "react"; +import { Helmet } from "@/lib/helmet"; +import { Link, useLocation, useNavigate } from "@/lib/router"; +import { api } from "@/lib/api"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import type * as Types from "@/lib/types"; +import { formatJalali, formatNumberPersian, formatToman, getThumbUrl } from "@/lib/utils"; +import { siteUrl } from "@/lib/site"; + +type EventsProps = { + initialEvents?: Types.EventListItemSchema[]; + initialSearch?: string; +}; + +function labelPrice(event: Types.EventListItemSchema) { + const price = Number(event?.price ?? 0); + return price <= 0 ? "رایگان" : formatToman(price); +} + +function modeFa(eventType: Types.EventListItemSchema["event_type"]) { + return eventType === "online" ? "آنلاین" : "حضوری"; +} + +function spotsLeft(event: Types.EventListItemSchema) { + const cap = Number(event.capacity); + const used = Number(event.registration_count); + return cap - used; +} + +function isAvailable(event: Types.EventListItemSchema) { + const now = new Date(); + const end = new Date(event.registration_end_date ?? event.start_time); + const timeOk = end.getTime() > now.getTime(); + return timeOk && spotsLeft(event) > 0; +} + +function notAvailableReasonFa(event: Types.EventListItemSchema) { + const now = new Date(); + const end = new Date(event.registration_end_date ?? event.start_time); + if (end.getTime() <= now.getTime()) return "ثبت‌نام پایان‌یافته"; + if (spotsLeft(event) <= 0) return "ظرفیت تکمیل"; + return "غیرقابل ثبت‌نام"; +} + +export default function Events({ + initialEvents = [], + initialSearch = "", +}: EventsProps) { + const navigate = useNavigate(); + const location = useLocation(); + const [events, setEvents] = useState(initialEvents); + const [search, setSearch] = useState(initialSearch); + const [loading, setLoading] = useState(!initialEvents.length && !initialSearch); + + const siteName = "East Guilan CE"; + const pageTitle = `Events | ${siteName}`; + const pageDescription = + "Discover upcoming and past events organized by the East Guilan Computer Engineering Association, including workshops, competitions, and community programs."; + const canonicalUrl = `${siteUrl}/events`; + + const toAbsoluteUrl = (url?: string | null) => { + if (!url) return undefined; + if (url.startsWith("http")) return url; + const normalizedSite = siteUrl.endsWith("/") ? siteUrl.slice(0, -1) : siteUrl; + const normalizedPath = url.startsWith("/") ? url.slice(1) : url; + return `${normalizedSite}/${normalizedPath}`; + }; + + const ogImage = useMemo(() => { + if (!events.length) return `${siteUrl}/favicon.ico`; + return toAbsoluteUrl(getThumbUrl(events[0])) ?? `${siteUrl}/favicon.ico`; + }, [events]); + + const listStructuredData = useMemo(() => { + if (!events.length) return null; + + const itemListElement = events.map((eventItem, index) => { + const listItem: Record = { + "@type": "ListItem", + position: index + 1, + url: `${siteUrl}/events/${eventItem.slug}`, + name: eventItem.title, + description: eventItem.description, + startDate: eventItem.start_time, + }; + + if (eventItem.end_time) { + listItem.endDate = eventItem.end_time; + } + + const imageUrl = toAbsoluteUrl(getThumbUrl(eventItem)); + if (imageUrl) { + listItem.image = imageUrl; + } + + const placeName = eventItem.location || eventItem.address; + if (placeName) { + const place: Record = { + "@type": "Place", + name: placeName, + }; + if (eventItem.address) { + place.address = eventItem.address; + } + listItem.location = place; + } + + return listItem; + }); + + return { + "@context": "https://schema.org", + "@type": "ItemList", + name: pageTitle, + description: pageDescription, + url: canonicalUrl, + numberOfItems: events.length, + itemListElement, + }; + }, [canonicalUrl, events, pageDescription, pageTitle]); + + useEffect(() => { + setEvents(initialEvents); + }, [initialEvents]); + + useEffect(() => { + setSearch(initialSearch); + }, [initialSearch]); + + const loadEvents = useCallback(async () => { + try { + setLoading(true); + const data = await api.getEvents({ + search: search || undefined, + statuses: ["published", "completed"], + limit: 30, + }); + setEvents(data); + } catch (error) { + console.error("Error loading events:", error); + } finally { + setLoading(false); + } + }, [search]); + + useEffect(() => { + loadEvents(); + }, [loadEvents]); + + useEffect(() => { + const params = new URLSearchParams(); + if (search.trim()) { + params.set("search", search.trim()); + } + const basePath = location.pathname || "/events"; + const nextPath = params.size + ? `${basePath}?${params.toString()}` + : basePath; + navigate(nextPath, { replace: true }); + }, [location.pathname, navigate, search]); + + return ( + <> + + {pageTitle} + + + + + + + + + + + + + + {listStructuredData && ( + + )} + + +
+
+

رویدادها

+ +
+ setSearch(e.target.value)} + className="max-w-md" + /> +
+ + {loading ? ( +

در حال بارگذاری...

+ ) : events.length === 0 ? ( +

رویدادی یافت نشد

+ ) : ( +
+ {events.map((event) => ( + + +
+ {event.title} +
+ +
+ +
+ {event.title} + {modeFa(event.event_type)} +
+ {formatJalali(event.start_time, false)} +
+ + +
+
+ ظرفیت رویداد + + {formatNumberPersian(Number(event?.capacity ?? 0) - Number(event?.registration_count ?? 0))} + / + {formatNumberPersian(Number(event?.capacity ?? 0))} نفر + +
+
+ هزینه‌ی ثبت‌نام + {labelPrice(event)} +
+ {isAvailable(event) ? ( + + ) : ( + + )} +
+
+
+
+ + ))} +
+ )} +
+
+ + ); +} diff --git a/src/pages/Home.tsx b/src/views/Home.tsx similarity index 98% rename from src/pages/Home.tsx rename to src/views/Home.tsx index 49a2bbe..1001021 100644 --- a/src/pages/Home.tsx +++ b/src/views/Home.tsx @@ -4,8 +4,8 @@ import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; -import { Helmet } from "react-helmet-async"; -import { Link } from "react-router-dom"; +import { Helmet } from "@/lib/helmet"; +import { Link } from "@/lib/router"; const heroTitle = "انجمن علمی کامپیوتر دانشگاه گیلان"; const heroDescription = diff --git a/src/pages/Logout.tsx b/src/views/Logout.tsx similarity index 94% rename from src/pages/Logout.tsx rename to src/views/Logout.tsx index a285cdf..3423a79 100644 --- a/src/pages/Logout.tsx +++ b/src/views/Logout.tsx @@ -1,5 +1,7 @@ +"use client"; + import { useEffect } from "react"; -import { useNavigate } from "react-router-dom"; +import { useNavigate } from "@/lib/router"; import { Loader2 } from "lucide-react"; import { useAuth } from "@/contexts/AuthContext"; import { useToast } from "@/hooks/use-toast"; diff --git a/src/pages/PaymentResult.tsx b/src/views/PaymentResult.tsx similarity index 97% rename from src/pages/PaymentResult.tsx rename to src/views/PaymentResult.tsx index 8c41fdb..9b41145 100644 --- a/src/pages/PaymentResult.tsx +++ b/src/views/PaymentResult.tsx @@ -1,6 +1,8 @@ +"use client"; + import { useEffect, useMemo, useState, useRef } from 'react'; -import { Helmet } from 'react-helmet-async'; -import { useSearchParams, Link } from 'react-router-dom'; +import { Helmet } from '@/lib/helmet'; +import { useSearchParams, Link } from '@/lib/router'; import QRCode from 'react-qr-code'; import jsPDF from 'jspdf'; import html2canvas from 'html2canvas'; @@ -9,6 +11,7 @@ import { Button } from '@/components/ui/button'; import { api } from '@/lib/api'; import { formatNumberPersian, formatToman, toPersianDigits } from '@/lib/utils'; import Markdown from '@/components/Markdown'; +import { siteUrl } from '@/lib/site'; type SavedPayment = { event_id: number; @@ -19,7 +22,7 @@ type SavedPayment = { discount_amount?: number; amount?: number; started_at?: string; - success_markdown?: string; + success_markdown?: string | null; }; @@ -63,7 +66,6 @@ export default function PaymentResult() { const receiptRef = useRef(null); const successMarkdown = data?.success_markdown ?? ''; - const siteUrl = 'https://east-guilan-ce.ir'; const siteName = 'East Guilan CE'; const canonicalUrl = `${siteUrl}/payments/result`; const toAbsoluteUrl = (url?: string | null) => { @@ -112,13 +114,13 @@ export default function PaymentResult() { const qrValue = useMemo(() => { // لینک قابل بررسی/اشتراک‌گذاری - const base = window.location.origin; + const base = typeof window !== 'undefined' ? window.location.origin : siteUrl; const url = new URL(`${base}/payments/result`); if (refId) url.searchParams.set('ref_id', refId); if (eventId) url.searchParams.set('event_id', String(eventId)); url.searchParams.set('status', ok ? 'success' : 'failed'); return url.toString(); - }, [refId, eventId, ok]); + }, [eventId, ok, refId]); const handleDownloadPdf = async () => { const el = receiptRef.current; diff --git a/src/pages/Profile.tsx b/src/views/Profile.tsx similarity index 99% rename from src/pages/Profile.tsx rename to src/views/Profile.tsx index 4802f12..ec25f01 100644 --- a/src/pages/Profile.tsx +++ b/src/views/Profile.tsx @@ -1,7 +1,9 @@ +"use client"; + import type * as Types from '@/lib/types'; import { useEffect, useRef, useState, useMemo } from 'react'; -import { Navigate, Link } from 'react-router-dom'; -import { Helmet } from 'react-helmet-async'; +import { Navigate, Link } from '@/lib/router'; +import { Helmet } from '@/lib/helmet'; import { useAuth } from '@/contexts/AuthContext'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; @@ -191,7 +193,7 @@ export default function Profile() { if (!me?.major) return '—'; if (majors) { const f = majors.find(m => m.code === me.major || m.label === me.major); - return f.label; + return f?.label ?? me.major; } return me.major; }, [majors, me?.major]); @@ -210,8 +212,9 @@ export default function Profile() { if (!me?.university) return '—'; if (universities) { const f = universities.find(u => u.code === me.university || u.label === me.university); - return f.label; + return f?.label ?? me.university; } + return me.university; }, [universities, me?.university]); const [uploading, setUploading] = useState(false); diff --git a/src/pages/ResetPasswordConfirm.tsx b/src/views/ResetPasswordConfirm.tsx similarity index 97% rename from src/pages/ResetPasswordConfirm.tsx rename to src/views/ResetPasswordConfirm.tsx index 36b7327..8352d4e 100644 --- a/src/pages/ResetPasswordConfirm.tsx +++ b/src/views/ResetPasswordConfirm.tsx @@ -1,5 +1,7 @@ +"use client"; + import { useState } from 'react'; -import { useParams, useNavigate } from 'react-router-dom'; +import { useParams, useNavigate } from '@/lib/router'; import { useToast } from '@/hooks/use-toast'; import { api } from '@/lib/api'; import { resolveErrorMessage } from '@/lib/utils'; diff --git a/src/pages/ResetPasswordRequest.tsx b/src/views/ResetPasswordRequest.tsx similarity index 99% rename from src/pages/ResetPasswordRequest.tsx rename to src/views/ResetPasswordRequest.tsx index 9d8f236..0975da8 100644 --- a/src/pages/ResetPasswordRequest.tsx +++ b/src/views/ResetPasswordRequest.tsx @@ -1,3 +1,5 @@ +"use client"; + import { useState } from 'react'; import { useToast } from '@/hooks/use-toast'; import { api } from '@/lib/api'; diff --git a/src/pages/VerifyEmail.tsx b/src/views/VerifyEmail.tsx similarity index 98% rename from src/pages/VerifyEmail.tsx rename to src/views/VerifyEmail.tsx index 518e9a5..3462105 100644 --- a/src/pages/VerifyEmail.tsx +++ b/src/views/VerifyEmail.tsx @@ -1,5 +1,7 @@ +"use client"; + import { useEffect } from "react"; -import { useParams, Link } from "react-router-dom"; +import { useParams, Link } from "@/lib/router"; import { useQuery } from "@tanstack/react-query"; import { api } from "@/lib/api"; import { diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts deleted file mode 100644 index 11f02fe..0000000 --- a/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/tsconfig.app.json b/tsconfig.app.json deleted file mode 100644 index 0b0e43e..0000000 --- a/tsconfig.app.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "isolatedModules": true, - "moduleDetection": "force", - "noEmit": true, - "jsx": "react-jsx", - - /* Linting */ - "strict": false, - "noUnusedLocals": false, - "noUnusedParameters": false, - "noImplicitAny": false, - "noFallthroughCasesInSwitch": false, - - "baseUrl": ".", - "paths": { - "@/*": ["./src/*"] - } - }, - "include": ["src"] -} diff --git a/tsconfig.json b/tsconfig.json index 2518773..64a86d3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,16 +1,42 @@ { - "files": [], - "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }], "compilerOptions": { + "target": "ES2017", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "strict": false, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, "baseUrl": ".", "paths": { - "@/*": ["./src/*"] + "@/*": [ + "./src/*" + ] }, - "noImplicitAny": false, - "noUnusedParameters": false, - "skipLibCheck": true, - "allowJs": true, - "noUnusedLocals": false, - "strictNullChecks": false - } -} + "plugins": [ + { + "name": "next" + } + ], + "strictNullChecks": true + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json deleted file mode 100644 index 3133162..0000000 --- a/tsconfig.node.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "lib": ["ES2023"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "isolatedModules": true, - "moduleDetection": "force", - "noEmit": true, - - /* Linting */ - "strict": true, - "noUnusedLocals": false, - "noUnusedParameters": false, - "noFallthroughCasesInSwitch": true - }, - "include": ["vite.config.ts"] -} diff --git a/vite.config.ts b/vite.config.ts deleted file mode 100644 index da25c6d..0000000 --- a/vite.config.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react-swc"; -import path from "path"; -import { componentTagger } from "lovable-tagger"; - -// https://vitejs.dev/config/ -export default defineConfig(({ mode }) => ({ - server: { - host: "::", - port: 8080, - }, - plugins: [react(), mode === "development" && componentTagger()].filter(Boolean), - resolve: { - alias: { - "@": path.resolve(__dirname, "./src"), - }, - }, -}));