tanstack_start_ts 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.wrangler/deploy/config.json +1 -0
- package/bunfig.toml +6 -0
- package/components.json +22 -0
- package/config.json +0 -0
- package/dist/client/.assetsignore +2 -0
- package/dist/client/assets/ProductCard-DbIkJAE-.js +1 -0
- package/dist/client/assets/about-AskxOruL.js +1 -0
- package/dist/client/assets/admin-BZVcAQM3.js +1 -0
- package/dist/client/assets/admin.functions--RdVcuBx.js +1 -0
- package/dist/client/assets/admin.login-QgrF_9Fp.js +1 -0
- package/dist/client/assets/affiliate-disclosure-BIAsA-HO.js +1 -0
- package/dist/client/assets/categories-D0N418mK.js +1 -0
- package/dist/client/assets/category._slug-aCaQm14E.js +1 -0
- package/dist/client/assets/contact-PhvO-V15.js +1 -0
- package/dist/client/assets/faq-BsiHWPM8.js +1 -0
- package/dist/client/assets/hero-bg-BP2eVUIX.jpg +0 -0
- package/dist/client/assets/index-BU9rnkF3.js +1 -0
- package/dist/client/assets/index-BpJWZkva.js +1 -0
- package/dist/client/assets/index-vRX-zAyq.js +1 -0
- package/dist/client/assets/login-DteE0ZGp.js +1 -0
- package/dist/client/assets/logo-pSNfLJQk.png +0 -0
- package/dist/client/assets/privacy-B_Pu7040.js +1 -0
- package/dist/client/assets/product-links-BkZ41Gv3.js +1 -0
- package/dist/client/assets/product._id-BVUysCW-.js +1 -0
- package/dist/client/assets/products.functions-cGzRziKO.js +1 -0
- package/dist/client/assets/profile-CveRcKq2.js +1 -0
- package/dist/client/assets/reset-password-ySEjItX_.js +1 -0
- package/dist/client/assets/saved-CHtdQDJF.js +1 -0
- package/dist/client/assets/search-CXWfET1y.js +1 -0
- package/dist/client/assets/signup-CEx90iuV.js +1 -0
- package/dist/client/assets/styles-DrNJG0BO.css +1 -0
- package/dist/client/assets/terms-VqJ9kX9b.js +1 -0
- package/dist/client/assets/update-password-C-d0ix5e.js +1 -0
- package/dist/client/assets/vendor-aria-hidden-DvXkyWUv.js +1 -0
- package/dist/client/assets/vendor-class-variance-authority-5VPnzWs2.js +1 -0
- package/dist/client/assets/vendor-clsx-B-dksMZM.js +1 -0
- package/dist/client/assets/vendor-cookie-es-CS0aJGDi.js +1 -0
- package/dist/client/assets/vendor-detect-node-es-l0sNRNKZ.js +1 -0
- package/dist/client/assets/vendor-floating-ui-core-BlUy28sp.js +1 -0
- package/dist/client/assets/vendor-floating-ui-dom-BxK0hn2R.js +1 -0
- package/dist/client/assets/vendor-floating-ui-react-dom-Bas3975S.js +1 -0
- package/dist/client/assets/vendor-floating-ui-utils-BfYUAVcw.js +1 -0
- package/dist/client/assets/vendor-framer-motion-BMdL-cuX.js +9 -0
- package/dist/client/assets/vendor-get-nonce-C-Z93AgS.js +1 -0
- package/dist/client/assets/vendor-iceberg-js-tWD4K6Lg.js +1 -0
- package/dist/client/assets/vendor-lovable.dev-cloud-auth-js-VuzqtJVg.js +1 -0
- package/dist/client/assets/vendor-lucide-react-b5K2fehp.js +1 -0
- package/dist/client/assets/vendor-motion-dom-BETJamZt.js +1 -0
- package/dist/client/assets/vendor-motion-utils-BuWewJbj.js +1 -0
- package/dist/client/assets/vendor-radix-ui-primitive-Dc_FVRD7.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-accordion-C22Rgxe9.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-arrow-DMHj2mKI.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-avatar-CVPBkFXg.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-collapsible-BvM-4sKX.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-collection-D9KtqmHm.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-compose-refs-Cvq0AS8Z.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-context-CAqqn5Nx.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-dialog-DZ01vOLq.js +5 -0
- package/dist/client/assets/vendor-radix-ui-react-direction-DxZwNuei.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-dismissable-layer-Dqgrs55Y.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-dropdown-menu-0uzvrqkn.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-focus-guards-DgWoZ-fP.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-focus-scope-BLIu5QaL.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-id-bpga_rLa.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-menu-D0qf2r6_.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-popper-BafIylxU.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-portal-BnAsfNCS.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-presence-C-f3UKQ2.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-primitive-zTHwXNoz.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-roving-focus-jyJB8K2E.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-slot-6LXHJrHl.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-use-callback-ref-E91aPc6s.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-use-controllable-state-Ca3eMtxa.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-use-effect-event-CPeX4A3c.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-use-escape-keydown-7n3YsXFo.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-use-is-hydrated-C1PY1qNv.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-use-layout-effect-B3AcGWPy.js +1 -0
- package/dist/client/assets/vendor-radix-ui-react-use-size-CXS04sct.js +1 -0
- package/dist/client/assets/vendor-react-dom-BnNs-kzm.js +9 -0
- package/dist/client/assets/vendor-react-gJPiVnX5.js +1 -0
- package/dist/client/assets/vendor-react-remove-scroll-DHKl-IMP.js +4 -0
- package/dist/client/assets/vendor-react-remove-scroll-bar-CSjdInc2.js +38 -0
- package/dist/client/assets/vendor-react-style-singleton-BqHpkgXn.js +1 -0
- package/dist/client/assets/vendor-scheduler-7OC5HNn7.js +1 -0
- package/dist/client/assets/vendor-seroval-B_Fur-nl.js +3 -0
- package/dist/client/assets/vendor-seroval-plugins-CBHnPkZJ.js +1 -0
- package/dist/client/assets/vendor-sonner-71-LdGG1.js +1 -0
- package/dist/client/assets/vendor-supabase-auth-js-DWrN-bIx.js +18 -0
- package/dist/client/assets/vendor-supabase-functions-js-uY_V-TxC.js +1 -0
- package/dist/client/assets/vendor-supabase-phoenix-BzEf37Ve.js +2 -0
- package/dist/client/assets/vendor-supabase-postgrest-js-C4rBWbCx.js +4 -0
- package/dist/client/assets/vendor-supabase-realtime-js-D6BlOYKE.js +23 -0
- package/dist/client/assets/vendor-supabase-storage-js-BG98L3Zz.js +1 -0
- package/dist/client/assets/vendor-supabase-supabase-js-DCCzdwBJ.js +1 -0
- package/dist/client/assets/vendor-tailwind-merge-Ct12j0u0.js +1 -0
- package/dist/client/assets/vendor-tanstack-history-C617CaxG.js +1 -0
- package/dist/client/assets/vendor-tanstack-query-core-7wuJJ5ZL.js +1 -0
- package/dist/client/assets/vendor-tanstack-react-query-HImzo8sX.js +1 -0
- package/dist/client/assets/vendor-tanstack-react-router-sIZLK-LU.js +1 -0
- package/dist/client/assets/vendor-tanstack-react-start-client-GiYCfWmf.js +1 -0
- package/dist/client/assets/vendor-tanstack-react-store-EvTi3ahh.js +1 -0
- package/dist/client/assets/vendor-tanstack-router-core-Cr7bYUZv.js +1 -0
- package/dist/client/assets/vendor-tanstack-start-client-core-C-00BBOu.js +2 -0
- package/dist/client/assets/vendor-tanstack-start-fn-stubs-l0sNRNKZ.js +1 -0
- package/dist/client/assets/vendor-tanstack-store-BC7mA7pq.js +1 -0
- package/dist/client/assets/vendor-tslib-Du-meQkk.js +1 -0
- package/dist/client/assets/vendor-use-callback-ref-C_fIAtot.js +1 -0
- package/dist/client/assets/vendor-use-sidecar-Bh0DDN6h.js +1 -0
- package/dist/client/assets/vendor-use-sync-external-store-ZvKHXaIn.js +1 -0
- package/dist/client/assets/vendor-vercel-analytics-DwPM5BWs.js +1 -0
- package/dist/client/assets/vendor-zod-By9teAtI.js +1 -0
- package/dist/client/robots.txt +2 -0
- package/dist/server/.dev.vars +5 -0
- package/dist/server/.vite/manifest.json +2528 -0
- package/dist/server/assets/ProductCard-CUPXy5Eo.js +149 -0
- package/dist/server/assets/_tanstack-start-manifest_v-do7vTWFD.js +4 -0
- package/dist/server/assets/about-TfKQw0Ga.js +28 -0
- package/dist/server/assets/admin-DspfJOJk.js +578 -0
- package/dist/server/assets/admin.functions-B78ppWLR.js +645 -0
- package/dist/server/assets/admin.functions-BWlKBoTL.js +93 -0
- package/dist/server/assets/admin.login-CV7QfeA6.js +139 -0
- package/dist/server/assets/affiliate-disclosure-B1wI1cDb.js +86 -0
- package/dist/server/assets/auth-middleware-Cn49MidW.js +62 -0
- package/dist/server/assets/categories-Z7jnAYZP.js +108 -0
- package/dist/server/assets/category._slug-D0XY3FGK.js +112 -0
- package/dist/server/assets/contact-IzyONsXs.js +104 -0
- package/dist/server/assets/faq-aRhB_CR3.js +133 -0
- package/dist/server/assets/hero-bg-BP2eVUIX.jpg +0 -0
- package/dist/server/assets/index-BTPHbXw9.js +221 -0
- package/dist/server/assets/index-ByJkHkrU.js +30 -0
- package/dist/server/assets/login-Dvy5Dm0f.js +175 -0
- package/dist/server/assets/logo-pSNfLJQk.png +0 -0
- package/dist/server/assets/privacy-B6Wiez1P.js +93 -0
- package/dist/server/assets/product-links-CGYEPP56.js +16 -0
- package/dist/server/assets/product._id-BpRa-1z0.js +231 -0
- package/dist/server/assets/products.functions-DSlmibYN.js +209 -0
- package/dist/server/assets/products.functions-DlHkRiqi.js +24 -0
- package/dist/server/assets/profile-B0NWzVAZ.js +314 -0
- package/dist/server/assets/reset-password-CY-rmqMr.js +115 -0
- package/dist/server/assets/saved-7FA6Dbom.js +126 -0
- package/dist/server/assets/search-Yw5c_fZa.js +329 -0
- package/dist/server/assets/signup-UPzgZo4i.js +143 -0
- package/dist/server/assets/styles-DrNJG0BO.css +1 -0
- package/dist/server/assets/terms-CMnX95bP.js +89 -0
- package/dist/server/assets/update-password-Cr94ea8n.js +131 -0
- package/dist/server/assets/vendor-aria-hidden-DPa16MWu.js +122 -0
- package/dist/server/assets/vendor-class-variance-authority-0YxJPB9Y.js +44 -0
- package/dist/server/assets/vendor-cloudflare-unenv-preset-ya0VEFBz.js +250 -0
- package/dist/server/assets/vendor-clsx-DgYk2OaC.js +16 -0
- package/dist/server/assets/vendor-cookie-es-DAoofYiI.js +44 -0
- package/dist/server/assets/vendor-detect-node-es-l0sNRNKZ.js +1 -0
- package/dist/server/assets/vendor-floating-ui-core-3tkK0THV.js +726 -0
- package/dist/server/assets/vendor-floating-ui-dom-C-cPtgJv.js +626 -0
- package/dist/server/assets/vendor-floating-ui-react-dom-CRG6gBpH.js +319 -0
- package/dist/server/assets/vendor-floating-ui-utils-DmXANH-E.js +320 -0
- package/dist/server/assets/vendor-framer-motion-X4zAkX3J.js +1979 -0
- package/dist/server/assets/vendor-get-nonce-DiSj3EHl.js +9 -0
- package/dist/server/assets/vendor-h3-v2-CCobnLY5.js +287 -0
- package/dist/server/assets/vendor-iceberg-js-bHCkXyJn.js +534 -0
- package/dist/server/assets/vendor-isbot-CZ7WjwVs.js +21 -0
- package/dist/server/assets/vendor-lovable.dev-cloud-auth-js-BE03njZw.js +180 -0
- package/dist/server/assets/vendor-lucide-react-Ddew6HYb.js +458 -0
- package/dist/server/assets/vendor-motion-dom-D2MTwGIG.js +5983 -0
- package/dist/server/assets/vendor-motion-utils-LJlIFN6m.js +161 -0
- package/dist/server/assets/vendor-radix-ui-primitive-B-mNdDrH.js +11 -0
- package/dist/server/assets/vendor-radix-ui-react-accordion-1Izf6x00.js +308 -0
- package/dist/server/assets/vendor-radix-ui-react-arrow-B882lnFK.js +23 -0
- package/dist/server/assets/vendor-radix-ui-react-avatar-BVgZt2Ab.js +209 -0
- package/dist/server/assets/vendor-radix-ui-react-collapsible-DCBbMZiS.js +147 -0
- package/dist/server/assets/vendor-radix-ui-react-collection-BZ2srfgU.js +150 -0
- package/dist/server/assets/vendor-radix-ui-react-compose-refs-D3qsKVk1.js +39 -0
- package/dist/server/assets/vendor-radix-ui-react-context-BVoNDLue.js +78 -0
- package/dist/server/assets/vendor-radix-ui-react-dialog-DlxMaNYK.js +406 -0
- package/dist/server/assets/vendor-radix-ui-react-direction-Dt_WDL1t.js +9 -0
- package/dist/server/assets/vendor-radix-ui-react-dismissable-layer-CjsuPohV.js +210 -0
- package/dist/server/assets/vendor-radix-ui-react-dropdown-menu-DVxKumY8.js +263 -0
- package/dist/server/assets/vendor-radix-ui-react-focus-guards-D_6NoePE.js +29 -0
- package/dist/server/assets/vendor-radix-ui-react-focus-scope-DEIhTJJH.js +206 -0
- package/dist/server/assets/vendor-radix-ui-react-id-DFFpgh6m.js +14 -0
- package/dist/server/assets/vendor-radix-ui-react-menu-CiTMLwjT.js +893 -0
- package/dist/server/assets/vendor-radix-ui-react-popper-23Ye2Vyc.js +286 -0
- package/dist/server/assets/vendor-radix-ui-react-portal-CZCH5uPk.js +16 -0
- package/dist/server/assets/vendor-radix-ui-react-presence-CaAULlDU.js +128 -0
- package/dist/server/assets/vendor-radix-ui-react-primitive-BeOk3UYa.js +124 -0
- package/dist/server/assets/vendor-radix-ui-react-roving-focus-DES9GR8l.js +224 -0
- package/dist/server/assets/vendor-radix-ui-react-slot-DUhZbzoH.js +103 -0
- package/dist/server/assets/vendor-radix-ui-react-use-callback-ref-BynBgohw.js +11 -0
- package/dist/server/assets/vendor-radix-ui-react-use-controllable-state-C9KpT6DG.js +69 -0
- package/dist/server/assets/vendor-radix-ui-react-use-effect-event-gpNY2xjS.js +1 -0
- package/dist/server/assets/vendor-radix-ui-react-use-escape-keydown-CcYRQ2pp.js +17 -0
- package/dist/server/assets/vendor-radix-ui-react-use-is-hydrated-D_LcBPXY.js +15 -0
- package/dist/server/assets/vendor-radix-ui-react-use-layout-effect-1LNLXAjr.js +6 -0
- package/dist/server/assets/vendor-radix-ui-react-use-size-D6fiKJQo.js +39 -0
- package/dist/server/assets/vendor-react-DvBrY0qp.js +511 -0
- package/dist/server/assets/vendor-react-dom-yvMLPM0j.js +10484 -0
- package/dist/server/assets/vendor-react-remove-scroll-BNtiEvVN.js +328 -0
- package/dist/server/assets/vendor-react-remove-scroll-bar-hLqRASRk.js +82 -0
- package/dist/server/assets/vendor-react-style-singleton-BXjcXskB.js +69 -0
- package/dist/server/assets/vendor-rou3-3NaGPdI8.js +8 -0
- package/dist/server/assets/vendor-seroval-dJyC-Zhz.js +1775 -0
- package/dist/server/assets/vendor-seroval-plugins-Pq_U2meB.js +58 -0
- package/dist/server/assets/vendor-sonner-CqbjhsRh.js +1086 -0
- package/dist/server/assets/vendor-srvx-BA-baEX9.js +6 -0
- package/dist/server/assets/vendor-supabase-auth-js-D4xjVprw.js +7602 -0
- package/dist/server/assets/vendor-supabase-functions-js-sWy4UYn1.js +322 -0
- package/dist/server/assets/vendor-supabase-phoenix-Bw3Uh2Nn.js +1777 -0
- package/dist/server/assets/vendor-supabase-postgrest-js-AO-BXa7I.js +4938 -0
- package/dist/server/assets/vendor-supabase-realtime-js-BtdNgJbm.js +2111 -0
- package/dist/server/assets/vendor-supabase-storage-js-Dk_MrPYO.js +2679 -0
- package/dist/server/assets/vendor-supabase-supabase-js-D1EEtG3j.js +697 -0
- package/dist/server/assets/vendor-tailwind-merge-BHb_obmC.js +3255 -0
- package/dist/server/assets/vendor-tanstack-history-C4pKJmkt.js +204 -0
- package/dist/server/assets/vendor-tanstack-query-core-PwwTR5ld.js +2552 -0
- package/dist/server/assets/vendor-tanstack-react-query-hhHzXAK1.js +190 -0
- package/dist/server/assets/vendor-tanstack-react-router-XzqpA65A.js +1120 -0
- package/dist/server/assets/vendor-tanstack-react-start-RvWUpvat.js +37 -0
- package/dist/server/assets/vendor-tanstack-react-start-client-gpNY2xjS.js +1 -0
- package/dist/server/assets/vendor-tanstack-react-start-server-uj_Y9pEN.js +15 -0
- package/dist/server/assets/vendor-tanstack-react-store-gpNY2xjS.js +1 -0
- package/dist/server/assets/vendor-tanstack-router-core-6wywV3KN.js +4252 -0
- package/dist/server/assets/vendor-tanstack-start-client-core-DoOKV2pA.js +1741 -0
- package/dist/server/assets/vendor-tanstack-start-fn-stubs-l0sNRNKZ.js +1 -0
- package/dist/server/assets/vendor-tanstack-start-server-core-CsAstXv7.js +1421 -0
- package/dist/server/assets/vendor-tanstack-start-storage-context-DgH9hIJT.js +17 -0
- package/dist/server/assets/vendor-tanstack-store-l0sNRNKZ.js +1 -0
- package/dist/server/assets/vendor-tslib-_8ICaZ64.js +67 -0
- package/dist/server/assets/vendor-unenv-DUvF4YIF.js +544 -0
- package/dist/server/assets/vendor-use-callback-ref-DMFDRvmi.js +66 -0
- package/dist/server/assets/vendor-use-sidecar-DG1tHua4.js +106 -0
- package/dist/server/assets/vendor-use-sync-external-store-rZ8vi0It.js +64 -0
- package/dist/server/assets/vendor-vercel-analytics-oP8BDp0L.js +168 -0
- package/dist/server/assets/vendor-zod-BRyQdbC-.js +3580 -0
- package/dist/server/index.js +158 -0
- package/dist/server/wrangler.json +1 -0
- package/enable-powershell.ps1 +7 -0
- package/eslint.config.js +41 -0
- package/lint.bat +4 -0
- package/package.json +95 -0
- package/public/robots.txt +2 -0
- package/run-npm-build.cjs +20 -0
- package/run-npm-build.js +20 -0
- package/src/assets/hero-bg.jpg +0 -0
- package/src/assets/logo.png +0 -0
- package/src/components/scrollsy/Footer.tsx +68 -0
- package/src/components/scrollsy/LiveTicker.tsx +31 -0
- package/src/components/scrollsy/Logo.tsx +28 -0
- package/src/components/scrollsy/Nav.tsx +255 -0
- package/src/components/scrollsy/ProductCard.tsx +190 -0
- package/src/components/scrollsy/ProductFilters.tsx +226 -0
- package/src/components/scrollsy/SupportWidget.tsx +197 -0
- package/src/components/ui/accordion.tsx +51 -0
- package/src/components/ui/alert-dialog.tsx +115 -0
- package/src/components/ui/alert.tsx +49 -0
- package/src/components/ui/aspect-ratio.tsx +5 -0
- package/src/components/ui/avatar.tsx +47 -0
- package/src/components/ui/badge.tsx +32 -0
- package/src/components/ui/breadcrumb.tsx +101 -0
- package/src/components/ui/button.tsx +49 -0
- package/src/components/ui/calendar.tsx +177 -0
- package/src/components/ui/card.tsx +55 -0
- package/src/components/ui/carousel.tsx +240 -0
- package/src/components/ui/chart.tsx +331 -0
- package/src/components/ui/checkbox.tsx +26 -0
- package/src/components/ui/collapsible.tsx +11 -0
- package/src/components/ui/command.tsx +143 -0
- package/src/components/ui/context-menu.tsx +187 -0
- package/src/components/ui/dialog.tsx +104 -0
- package/src/components/ui/drawer.tsx +98 -0
- package/src/components/ui/dropdown-menu.tsx +188 -0
- package/src/components/ui/form.tsx +171 -0
- package/src/components/ui/hover-card.tsx +27 -0
- package/src/components/ui/input-otp.tsx +69 -0
- package/src/components/ui/input.tsx +22 -0
- package/src/components/ui/label.tsx +21 -0
- package/src/components/ui/menubar.tsx +229 -0
- package/src/components/ui/navigation-menu.tsx +120 -0
- package/src/components/ui/pagination.tsx +98 -0
- package/src/components/ui/popover.tsx +31 -0
- package/src/components/ui/progress.tsx +25 -0
- package/src/components/ui/radio-group.tsx +36 -0
- package/src/components/ui/resizable.tsx +37 -0
- package/src/components/ui/scroll-area.tsx +44 -0
- package/src/components/ui/select.tsx +152 -0
- package/src/components/ui/separator.tsx +24 -0
- package/src/components/ui/sheet.tsx +122 -0
- package/src/components/ui/sidebar.tsx +744 -0
- package/src/components/ui/skeleton.tsx +7 -0
- package/src/components/ui/slider.tsx +23 -0
- package/src/components/ui/sonner.tsx +23 -0
- package/src/components/ui/switch.tsx +27 -0
- package/src/components/ui/table.tsx +94 -0
- package/src/components/ui/tabs.tsx +53 -0
- package/src/components/ui/textarea.tsx +21 -0
- package/src/components/ui/toggle-group.tsx +57 -0
- package/src/components/ui/toggle.tsx +42 -0
- package/src/components/ui/tooltip.tsx +32 -0
- package/src/hooks/use-auth.ts +26 -0
- package/src/hooks/use-mobile.tsx +19 -0
- package/src/integrations/lovable/index.ts +41 -0
- package/src/lib/admin.functions.ts +564 -0
- package/src/lib/error-capture.ts +27 -0
- package/src/lib/error-page.ts +30 -0
- package/src/lib/product-links.ts +39 -0
- package/src/lib/products.functions.ts +101 -0
- package/src/lib/utils.ts +6 -0
- package/src/routeTree.gen.ts +480 -0
- package/src/router.tsx +16 -0
- package/src/routes/__root.tsx +177 -0
- package/src/routes/about.tsx +66 -0
- package/src/routes/admin.login.tsx +95 -0
- package/src/routes/admin.tsx +811 -0
- package/src/routes/affiliate-disclosure.tsx +35 -0
- package/src/routes/categories.tsx +57 -0
- package/src/routes/category.$slug.tsx +51 -0
- package/src/routes/contact.tsx +69 -0
- package/src/routes/faq.tsx +63 -0
- package/src/routes/index.tsx +269 -0
- package/src/routes/login.tsx +160 -0
- package/src/routes/privacy.tsx +39 -0
- package/src/routes/product.$id.tsx +212 -0
- package/src/routes/profile.tsx +393 -0
- package/src/routes/reset-password.tsx +71 -0
- package/src/routes/saved.tsx +83 -0
- package/src/routes/search.tsx +136 -0
- package/src/routes/signup.tsx +108 -0
- package/src/routes/sitemap[.]xml.ts +34 -0
- package/src/routes/terms.tsx +40 -0
- package/src/routes/update-password.tsx +91 -0
- package/src/server.ts +80 -0
- package/src/start.ts +24 -0
- package/src/styles.css +333 -0
- package/terminal-test-output.txt +1 -0
- package/tsconfig.json +27 -0
- package/vercel.json +26 -0
- package/vite.config.ts +38 -0
- package/wrangler.jsonc +7 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { createFileRoute, Link, useNavigate } from "@tanstack/react-router";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { supabase } from "@/integrations/supabase/client";
|
|
4
|
+
import { lovable } from "@/integrations/lovable";
|
|
5
|
+
import { Logo } from "@/components/scrollsy/Logo";
|
|
6
|
+
import { toast } from "sonner";
|
|
7
|
+
import { Mail, Lock, Sparkles } from "lucide-react";
|
|
8
|
+
|
|
9
|
+
export const Route = createFileRoute("/login")({
|
|
10
|
+
head: () => ({ meta: [{ title: "Log in · Scrollsy" }] }),
|
|
11
|
+
component: Login,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
function Login() {
|
|
15
|
+
const nav = useNavigate();
|
|
16
|
+
const [email, setEmail] = useState("");
|
|
17
|
+
const [password, setPassword] = useState("");
|
|
18
|
+
const [loading, setLoading] = useState(false);
|
|
19
|
+
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
supabase.auth.getSession().then(({ data }) => {
|
|
22
|
+
if (data.session) nav({ to: "/" });
|
|
23
|
+
});
|
|
24
|
+
}, [nav]);
|
|
25
|
+
|
|
26
|
+
const onEmail = async (e: React.FormEvent) => {
|
|
27
|
+
e.preventDefault();
|
|
28
|
+
setLoading(true);
|
|
29
|
+
const { error } = await supabase.auth.signInWithPassword({ email, password });
|
|
30
|
+
setLoading(false);
|
|
31
|
+
if (error) return toast.error(error.message);
|
|
32
|
+
toast.success("Welcome back!");
|
|
33
|
+
nav({ to: "/" });
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const onGoogle = async () => {
|
|
37
|
+
const result = await lovable.auth.signInWithOAuth("google", {
|
|
38
|
+
redirect_uri: window.location.origin,
|
|
39
|
+
});
|
|
40
|
+
if (result.error) return toast.error("Sign-in failed");
|
|
41
|
+
if (result.redirected) return;
|
|
42
|
+
nav({ to: "/" });
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<div className="min-h-[80vh] flex items-center justify-center px-4 py-16">
|
|
47
|
+
<div className="w-full max-w-md glass-strong rounded-3xl p-8 shadow-elevated animate-scale-in">
|
|
48
|
+
<div className="flex justify-center mb-2">
|
|
49
|
+
<Logo size={40} />
|
|
50
|
+
</div>
|
|
51
|
+
<h1 className="font-display text-3xl font-bold text-center mt-4">Welcome back</h1>
|
|
52
|
+
<p className="text-center text-sm text-muted-foreground mt-1">
|
|
53
|
+
Sign in to save your favorite finds
|
|
54
|
+
</p>
|
|
55
|
+
|
|
56
|
+
<button
|
|
57
|
+
onClick={onGoogle}
|
|
58
|
+
className="mt-6 w-full glass rounded-full py-3 font-medium text-sm hover:bg-white/10 transition flex items-center justify-center gap-2"
|
|
59
|
+
>
|
|
60
|
+
<GoogleIcon /> Continue with Google
|
|
61
|
+
</button>
|
|
62
|
+
|
|
63
|
+
<div className="my-5 flex items-center gap-3 text-xs text-muted-foreground">
|
|
64
|
+
<div className="flex-1 h-px bg-white/10" /> or <div className="flex-1 h-px bg-white/10" />
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<form onSubmit={onEmail} className="space-y-3">
|
|
68
|
+
<Field
|
|
69
|
+
icon={<Mail className="w-4 h-4" />}
|
|
70
|
+
type="email"
|
|
71
|
+
value={email}
|
|
72
|
+
onChange={setEmail}
|
|
73
|
+
placeholder="Email"
|
|
74
|
+
/>
|
|
75
|
+
<Field
|
|
76
|
+
icon={<Lock className="w-4 h-4" />}
|
|
77
|
+
type="password"
|
|
78
|
+
value={password}
|
|
79
|
+
onChange={setPassword}
|
|
80
|
+
placeholder="Password"
|
|
81
|
+
/>
|
|
82
|
+
<button
|
|
83
|
+
disabled={loading}
|
|
84
|
+
className="btn-glow w-full rounded-full py-3 font-semibold text-sm inline-flex items-center justify-center gap-2 disabled:opacity-60"
|
|
85
|
+
>
|
|
86
|
+
<Sparkles className="w-4 h-4" /> {loading ? "Signing in…" : "Sign in"}
|
|
87
|
+
</button>
|
|
88
|
+
</form>
|
|
89
|
+
|
|
90
|
+
<div className="mt-6 text-sm text-center text-muted-foreground space-y-2">
|
|
91
|
+
<p>
|
|
92
|
+
Forgot your password?{" "}
|
|
93
|
+
<Link
|
|
94
|
+
to="/reset-password"
|
|
95
|
+
className="text-foreground font-semibold hover:text-gradient"
|
|
96
|
+
>
|
|
97
|
+
Reset it
|
|
98
|
+
</Link>
|
|
99
|
+
</p>
|
|
100
|
+
<p>
|
|
101
|
+
New here?{" "}
|
|
102
|
+
<Link to="/signup" className="text-foreground font-semibold hover:text-gradient">
|
|
103
|
+
Create account
|
|
104
|
+
</Link>
|
|
105
|
+
</p>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function Field({
|
|
113
|
+
icon,
|
|
114
|
+
value,
|
|
115
|
+
onChange,
|
|
116
|
+
type = "text",
|
|
117
|
+
placeholder,
|
|
118
|
+
}: {
|
|
119
|
+
icon: React.ReactNode;
|
|
120
|
+
value: string;
|
|
121
|
+
onChange: (v: string) => void;
|
|
122
|
+
type?: string;
|
|
123
|
+
placeholder?: string;
|
|
124
|
+
}) {
|
|
125
|
+
return (
|
|
126
|
+
<label className="flex items-center gap-2 glass rounded-xl px-3 py-2.5">
|
|
127
|
+
<span className="text-muted-foreground">{icon}</span>
|
|
128
|
+
<input
|
|
129
|
+
type={type}
|
|
130
|
+
value={value}
|
|
131
|
+
onChange={(e) => onChange(e.target.value)}
|
|
132
|
+
placeholder={placeholder}
|
|
133
|
+
className="flex-1 bg-transparent outline-none text-sm placeholder:text-muted-foreground"
|
|
134
|
+
/>
|
|
135
|
+
</label>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function GoogleIcon() {
|
|
140
|
+
return (
|
|
141
|
+
<svg width="16" height="16" viewBox="0 0 48 48" aria-hidden="true">
|
|
142
|
+
<path
|
|
143
|
+
fill="#20b47c"
|
|
144
|
+
d="M43.6 20.5H42V20H24v8h11.3C33.7 32.7 29.3 36 24 36c-6.6 0-12-5.4-12-12s5.4-12 12-12c3.1 0 5.9 1.2 8 3.1l5.7-5.7C34.5 6 29.5 4 24 4 12.9 4 4 12.9 4 24s8.9 20 20 20 20-8.9 20-20c0-1.3-.1-2.3-.4-3.5z"
|
|
145
|
+
/>
|
|
146
|
+
<path
|
|
147
|
+
fill="#9e0ea3"
|
|
148
|
+
d="M6.3 14.7l6.6 4.8C14.7 16 19 13 24 13c3.1 0 5.9 1.2 8 3.1l5.7-5.7C34.5 7 29.5 5 24 5 16.3 5 9.7 9.4 6.3 14.7z"
|
|
149
|
+
/>
|
|
150
|
+
<path
|
|
151
|
+
fill="#59e9f3"
|
|
152
|
+
d="M24 44c5.4 0 10.3-2.1 14-5.4l-6.5-5.3C29.6 34.8 26.9 36 24 36c-5.3 0-9.7-3.3-11.3-7.9l-6.5 5C9.6 39.6 16.2 44 24 44z"
|
|
153
|
+
/>
|
|
154
|
+
<path
|
|
155
|
+
fill="#e64ce6"
|
|
156
|
+
d="M43.6 20.5H42V20H24v8h11.3c-.8 2.3-2.3 4.2-4.2 5.6l6.5 5.3C42 35 44 30 44 24c0-1.3-.1-2.3-.4-3.5z"
|
|
157
|
+
/>
|
|
158
|
+
</svg>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
2
|
+
import { Prose } from "./about";
|
|
3
|
+
|
|
4
|
+
export const Route = createFileRoute("/privacy")({
|
|
5
|
+
head: () => ({
|
|
6
|
+
meta: [
|
|
7
|
+
{ title: "Privacy Policy · Scrollsy" },
|
|
8
|
+
{ name: "description", content: "How Scrollsy collects, uses and protects your data." },
|
|
9
|
+
],
|
|
10
|
+
}),
|
|
11
|
+
component: () => (
|
|
12
|
+
<Prose title="Privacy Policy" subtitle="Last updated May 2026">
|
|
13
|
+
<p>Your privacy matters. This policy explains what we collect and how we use it.</p>
|
|
14
|
+
<h2>Information we collect</h2>
|
|
15
|
+
<ul>
|
|
16
|
+
<li>Account info (email, display name) when you sign up.</li>
|
|
17
|
+
<li>Saved items and browsing activity to personalize recommendations.</li>
|
|
18
|
+
<li>Anonymous analytics (page views, clicks) to improve the product.</li>
|
|
19
|
+
</ul>
|
|
20
|
+
<h2>How we use it</h2>
|
|
21
|
+
<p>
|
|
22
|
+
To run Scrollsy, deliver recommendations, send transactional emails and improve the
|
|
23
|
+
platform. We don't sell your personal data.
|
|
24
|
+
</p>
|
|
25
|
+
<h2>Affiliate clicks</h2>
|
|
26
|
+
<p>
|
|
27
|
+
When you click an affiliate link, the destination retailer may set cookies and collect their
|
|
28
|
+
own data per their privacy policy.
|
|
29
|
+
</p>
|
|
30
|
+
<h2>Your choices</h2>
|
|
31
|
+
<p>
|
|
32
|
+
You can edit your profile, delete saved items, or close your account at any time from your
|
|
33
|
+
profile page.
|
|
34
|
+
</p>
|
|
35
|
+
<h2>Contact</h2>
|
|
36
|
+
<p>Questions? Email privacy@scrollsy.app.</p>
|
|
37
|
+
</Prose>
|
|
38
|
+
),
|
|
39
|
+
});
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { createFileRoute, Link, notFound } from "@tanstack/react-router";
|
|
2
|
+
import { useQuery } from "@tanstack/react-query";
|
|
3
|
+
import { getProduct } from "@/lib/products.functions";
|
|
4
|
+
import { ProductCard } from "@/components/scrollsy/ProductCard";
|
|
5
|
+
import {
|
|
6
|
+
ExternalLink,
|
|
7
|
+
Heart,
|
|
8
|
+
Share2,
|
|
9
|
+
Truck,
|
|
10
|
+
Flame,
|
|
11
|
+
TrendingUp,
|
|
12
|
+
ChevronLeft,
|
|
13
|
+
ShieldCheck,
|
|
14
|
+
} from "lucide-react";
|
|
15
|
+
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
16
|
+
import { supabase } from "@/integrations/supabase/client";
|
|
17
|
+
import { useAuth } from "@/hooks/use-auth";
|
|
18
|
+
import { toast } from "sonner";
|
|
19
|
+
|
|
20
|
+
export const Route = createFileRoute("/product/$id")({
|
|
21
|
+
head: () => ({
|
|
22
|
+
meta: [{ title: "Product · Scrollsy" }],
|
|
23
|
+
}),
|
|
24
|
+
component: ProductPage,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
function ProductPage() {
|
|
28
|
+
const { id } = Route.useParams();
|
|
29
|
+
const { user } = useAuth();
|
|
30
|
+
const qc = useQueryClient();
|
|
31
|
+
|
|
32
|
+
const { data, isLoading } = useQuery({
|
|
33
|
+
queryKey: ["product", id],
|
|
34
|
+
queryFn: () => getProduct({ data: { id } }),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const { data: savedIds } = useQuery({
|
|
38
|
+
queryKey: ["saved-ids", user?.id],
|
|
39
|
+
enabled: !!user,
|
|
40
|
+
queryFn: async () => {
|
|
41
|
+
const { data } = await supabase
|
|
42
|
+
.from("saved_items")
|
|
43
|
+
.select("product_id")
|
|
44
|
+
.eq("user_id", user!.id);
|
|
45
|
+
return new Set((data ?? []).map((r) => r.product_id));
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
if (!isLoading && !data?.product) throw notFound();
|
|
50
|
+
const p = data?.product;
|
|
51
|
+
|
|
52
|
+
const toggleSave = useMutation({
|
|
53
|
+
mutationFn: async () => {
|
|
54
|
+
if (!user) throw new Error("login");
|
|
55
|
+
const isSaved = savedIds?.has(id);
|
|
56
|
+
if (isSaved) {
|
|
57
|
+
await supabase.from("saved_items").delete().eq("user_id", user.id).eq("product_id", id);
|
|
58
|
+
} else {
|
|
59
|
+
await supabase.from("saved_items").insert({ user_id: user.id, product_id: id });
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
onSuccess: () => {
|
|
63
|
+
qc.invalidateQueries({ queryKey: ["saved-ids", user?.id] });
|
|
64
|
+
toast.success("Updated favorites");
|
|
65
|
+
},
|
|
66
|
+
onError: (e: Error) => {
|
|
67
|
+
if (e.message === "login") toast.error("Sign in to save items");
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const share = async () => {
|
|
72
|
+
if (typeof navigator !== "undefined" && navigator.share) {
|
|
73
|
+
await navigator.share({ title: p?.title, url: window.location.href });
|
|
74
|
+
} else {
|
|
75
|
+
navigator.clipboard.writeText(window.location.href);
|
|
76
|
+
toast.success("Link copied");
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
if (!p) return <div className="px-4 max-w-7xl mx-auto pt-10">Loading…</div>;
|
|
81
|
+
|
|
82
|
+
const discount = p.original_price
|
|
83
|
+
? Math.round((1 - Number(p.price) / Number(p.original_price)) * 100)
|
|
84
|
+
: 0;
|
|
85
|
+
const isSaved = savedIds?.has(id) ?? false;
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<div className="px-4 max-w-7xl mx-auto pt-8">
|
|
89
|
+
<Link
|
|
90
|
+
to="/"
|
|
91
|
+
className="inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground"
|
|
92
|
+
>
|
|
93
|
+
<ChevronLeft className="w-4 h-4" /> Back
|
|
94
|
+
</Link>
|
|
95
|
+
|
|
96
|
+
<div className="mt-6 grid md:grid-cols-2 gap-8">
|
|
97
|
+
<div className="relative rounded-3xl overflow-hidden border border-white/5 bg-gradient-card">
|
|
98
|
+
<img src={p.image_url} alt={p.title} className="w-full h-auto object-cover" />
|
|
99
|
+
<div className="absolute top-4 left-4 flex flex-col gap-2">
|
|
100
|
+
{discount > 0 && (
|
|
101
|
+
<span className="bg-gradient-brand text-white text-sm font-bold px-3 py-1.5 rounded-full">
|
|
102
|
+
-{discount}% off
|
|
103
|
+
</span>
|
|
104
|
+
)}
|
|
105
|
+
{p.is_hot && (
|
|
106
|
+
<span className="glass-strong text-xs font-semibold px-3 py-1.5 rounded-full inline-flex items-center gap-1">
|
|
107
|
+
<Flame className="w-3.5 h-3.5 text-brand-orange" /> Hot Deal
|
|
108
|
+
</span>
|
|
109
|
+
)}
|
|
110
|
+
{p.is_trending && (
|
|
111
|
+
<span className="glass-strong text-xs font-semibold px-3 py-1.5 rounded-full inline-flex items-center gap-1">
|
|
112
|
+
<TrendingUp className="w-3.5 h-3.5 text-brand-magenta" /> Trending
|
|
113
|
+
</span>
|
|
114
|
+
)}
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<div className="space-y-5">
|
|
119
|
+
{(p as any).categories?.slug && (
|
|
120
|
+
<Link
|
|
121
|
+
to="/category/$slug"
|
|
122
|
+
params={{ slug: (p as any).categories.slug }}
|
|
123
|
+
className="inline-flex glass rounded-full px-3 py-1 text-xs"
|
|
124
|
+
>
|
|
125
|
+
{(p as any).categories.name}
|
|
126
|
+
</Link>
|
|
127
|
+
)}
|
|
128
|
+
<h1 className="font-display text-3xl md:text-4xl font-bold tracking-tight">{p.title}</h1>
|
|
129
|
+
<p className="text-muted-foreground">{p.description}</p>
|
|
130
|
+
|
|
131
|
+
<div className="flex items-baseline gap-3">
|
|
132
|
+
<span className="text-4xl font-display font-bold text-gradient">
|
|
133
|
+
${Number(p.price).toFixed(2)}
|
|
134
|
+
</span>
|
|
135
|
+
{p.original_price && (
|
|
136
|
+
<span className="text-lg text-muted-foreground line-through">
|
|
137
|
+
${Number(p.original_price).toFixed(2)}
|
|
138
|
+
</span>
|
|
139
|
+
)}
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
<div className="glass rounded-2xl p-4 space-y-2 text-sm">
|
|
143
|
+
{p.shipping_info && (
|
|
144
|
+
<div className="flex items-center gap-2">
|
|
145
|
+
<Truck className="w-4 h-4 text-brand-magenta" />
|
|
146
|
+
<span className="text-muted-foreground">{p.shipping_info}</span>
|
|
147
|
+
{p.delivery_estimate && (
|
|
148
|
+
<span className="text-muted-foreground">· {p.delivery_estimate}</span>
|
|
149
|
+
)}
|
|
150
|
+
</div>
|
|
151
|
+
)}
|
|
152
|
+
{p.merchant && (
|
|
153
|
+
<div className="flex items-center gap-2">
|
|
154
|
+
<ShieldCheck className="w-4 h-4 text-brand-magenta" />
|
|
155
|
+
<span className="text-muted-foreground">Sold via {p.merchant}</span>
|
|
156
|
+
</div>
|
|
157
|
+
)}
|
|
158
|
+
</div>
|
|
159
|
+
|
|
160
|
+
{p.tags?.length > 0 && (
|
|
161
|
+
<div className="flex flex-wrap gap-1.5">
|
|
162
|
+
{p.tags.map((t) => (
|
|
163
|
+
<span
|
|
164
|
+
key={t}
|
|
165
|
+
className="glass rounded-full px-2.5 py-1 text-[11px] text-muted-foreground"
|
|
166
|
+
>
|
|
167
|
+
#{t}
|
|
168
|
+
</span>
|
|
169
|
+
))}
|
|
170
|
+
</div>
|
|
171
|
+
)}
|
|
172
|
+
|
|
173
|
+
<div className="flex gap-2 pt-2">
|
|
174
|
+
<a
|
|
175
|
+
href={p.affiliate_url}
|
|
176
|
+
target="_blank"
|
|
177
|
+
rel="noopener noreferrer sponsored"
|
|
178
|
+
className="btn-glow flex-1 rounded-full py-3 font-semibold inline-flex items-center justify-center gap-2"
|
|
179
|
+
>
|
|
180
|
+
View Deal <ExternalLink className="w-4 h-4" />
|
|
181
|
+
</a>
|
|
182
|
+
<button
|
|
183
|
+
onClick={() => toggleSave.mutate()}
|
|
184
|
+
className={`glass-strong rounded-full px-4 ${isSaved ? "bg-gradient-brand border-transparent" : ""}`}
|
|
185
|
+
aria-label="Save"
|
|
186
|
+
>
|
|
187
|
+
<Heart className={isSaved ? "fill-white text-white" : ""} />
|
|
188
|
+
</button>
|
|
189
|
+
<button onClick={share} className="glass-strong rounded-full px-4" aria-label="Share">
|
|
190
|
+
<Share2 className="w-5 h-5" />
|
|
191
|
+
</button>
|
|
192
|
+
</div>
|
|
193
|
+
|
|
194
|
+
<p className="text-[11px] text-muted-foreground/80 pt-2">
|
|
195
|
+
Scrollsy may earn a commission from purchases through this link.
|
|
196
|
+
</p>
|
|
197
|
+
</div>
|
|
198
|
+
</div>
|
|
199
|
+
|
|
200
|
+
{(data?.related ?? []).length > 0 && (
|
|
201
|
+
<div className="mt-20">
|
|
202
|
+
<h2 className="font-display text-2xl font-bold mb-6">You might also love</h2>
|
|
203
|
+
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
|
204
|
+
{data!.related.map((r: any) => (
|
|
205
|
+
<ProductCard key={r.id} product={r} aspect="tall" />
|
|
206
|
+
))}
|
|
207
|
+
</div>
|
|
208
|
+
</div>
|
|
209
|
+
)}
|
|
210
|
+
</div>
|
|
211
|
+
);
|
|
212
|
+
}
|