@doswiftly/cli 0.1.1
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/README.md +357 -0
- package/bin/doswiftly.js +2 -0
- package/dist/commands/auth-github.d.ts +6 -0
- package/dist/commands/auth-github.d.ts.map +1 -0
- package/dist/commands/auth-github.js +89 -0
- package/dist/commands/auth-github.js.map +1 -0
- package/dist/commands/auth-token.d.ts +12 -0
- package/dist/commands/auth-token.d.ts.map +1 -0
- package/dist/commands/auth-token.js +43 -0
- package/dist/commands/auth-token.js.map +1 -0
- package/dist/commands/auth.d.ts +22 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +348 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/check.d.ts +5 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +234 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/config.d.ts +3 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +104 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/deploy.d.ts +37 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +580 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/dev.d.ts +8 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +83 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +363 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/domain.d.ts +13 -0
- package/dist/commands/domain.d.ts.map +1 -0
- package/dist/commands/domain.js +128 -0
- package/dist/commands/domain.js.map +1 -0
- package/dist/commands/env.d.ts +25 -0
- package/dist/commands/env.d.ts.map +1 -0
- package/dist/commands/env.js +228 -0
- package/dist/commands/env.js.map +1 -0
- package/dist/commands/init.d.ts +11 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +1028 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/inspect.d.ts +12 -0
- package/dist/commands/inspect.d.ts.map +1 -0
- package/dist/commands/inspect.js +162 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/commands/migrate.d.ts +18 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +355 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/preview.d.ts +29 -0
- package/dist/commands/preview.d.ts.map +1 -0
- package/dist/commands/preview.js +199 -0
- package/dist/commands/preview.js.map +1 -0
- package/dist/commands/proxy.d.ts +9 -0
- package/dist/commands/proxy.d.ts.map +1 -0
- package/dist/commands/proxy.js +37 -0
- package/dist/commands/proxy.js.map +1 -0
- package/dist/commands/sdk.d.ts +5 -0
- package/dist/commands/sdk.d.ts.map +1 -0
- package/dist/commands/sdk.js +82 -0
- package/dist/commands/sdk.js.map +1 -0
- package/dist/commands/template.d.ts +107 -0
- package/dist/commands/template.d.ts.map +1 -0
- package/dist/commands/template.js +1309 -0
- package/dist/commands/template.js.map +1 -0
- package/dist/commands/types.d.ts +5 -0
- package/dist/commands/types.d.ts.map +1 -0
- package/dist/commands/types.js +82 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/commands/update.d.ts +2 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +103 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/upgrade.d.ts +18 -0
- package/dist/commands/upgrade.d.ts.map +1 -0
- package/dist/commands/upgrade.js +55 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/commands/verify.d.ts +5 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +232 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/commands/whoami.d.ts +5 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +60 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/config/types.d.ts +173 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +48 -0
- package/dist/config/types.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +416 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api-url.d.ts +14 -0
- package/dist/lib/api-url.d.ts.map +1 -0
- package/dist/lib/api-url.js +24 -0
- package/dist/lib/api-url.js.map +1 -0
- package/dist/lib/api.d.ts +67 -0
- package/dist/lib/api.d.ts.map +1 -0
- package/dist/lib/api.js +36 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/config.d.ts +39 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +195 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/env-storage.d.ts +140 -0
- package/dist/lib/env-storage.d.ts.map +1 -0
- package/dist/lib/env-storage.js +464 -0
- package/dist/lib/env-storage.js.map +1 -0
- package/dist/lib/errors.d.ts +61 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +204 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/i18n.d.ts +99 -0
- package/dist/lib/i18n.d.ts.map +1 -0
- package/dist/lib/i18n.js +184 -0
- package/dist/lib/i18n.js.map +1 -0
- package/dist/lib/logger.d.ts +95 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +168 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/package-manager.d.ts +91 -0
- package/dist/lib/package-manager.d.ts.map +1 -0
- package/dist/lib/package-manager.js +205 -0
- package/dist/lib/package-manager.js.map +1 -0
- package/dist/lib/proxy-server.d.ts +24 -0
- package/dist/lib/proxy-server.d.ts.map +1 -0
- package/dist/lib/proxy-server.js +173 -0
- package/dist/lib/proxy-server.js.map +1 -0
- package/dist/lib/select-with-back.d.ts +34 -0
- package/dist/lib/select-with-back.d.ts.map +1 -0
- package/dist/lib/select-with-back.js +94 -0
- package/dist/lib/select-with-back.js.map +1 -0
- package/dist/lib/shared-api-client.d.ts +40 -0
- package/dist/lib/shared-api-client.d.ts.map +1 -0
- package/dist/lib/shared-api-client.js +92 -0
- package/dist/lib/shared-api-client.js.map +1 -0
- package/dist/lib/wizard-engine.d.ts +128 -0
- package/dist/lib/wizard-engine.d.ts.map +1 -0
- package/dist/lib/wizard-engine.js +168 -0
- package/dist/lib/wizard-engine.js.map +1 -0
- package/package.json +85 -0
- package/templates/storefront-minimal/.env.example +10 -0
- package/templates/storefront-minimal/.github/workflows/build-template.yml +109 -0
- package/templates/storefront-minimal/app/globals.css +18 -0
- package/templates/storefront-minimal/app/layout.tsx +26 -0
- package/templates/storefront-minimal/app/page.tsx +93 -0
- package/templates/storefront-minimal/lib/graphql-client.ts +23 -0
- package/templates/storefront-minimal/next.config.ts +15 -0
- package/templates/storefront-minimal/open-next.config.ts +3 -0
- package/templates/storefront-minimal/package.json +30 -0
- package/templates/storefront-minimal/postcss.config.mjs +5 -0
- package/templates/storefront-minimal/tailwind.config.ts +14 -0
- package/templates/storefront-minimal/tsconfig.json +27 -0
- package/templates/storefront-minimal/wrangler.toml +9 -0
- package/templates/storefront-nextjs/.env.example +68 -0
- package/templates/storefront-nextjs/.github/workflows/build-template.yml +109 -0
- package/templates/storefront-nextjs/.github/workflows/deploy.yml +25 -0
- package/templates/storefront-nextjs/.github/workflows/preview.yml +22 -0
- package/templates/storefront-nextjs/README.md +520 -0
- package/templates/storefront-nextjs/app/account/orders/page.tsx +216 -0
- package/templates/storefront-nextjs/app/account/page.tsx +167 -0
- package/templates/storefront-nextjs/app/auth/login/page.tsx +135 -0
- package/templates/storefront-nextjs/app/auth/register/page.tsx +228 -0
- package/templates/storefront-nextjs/app/cart/page.tsx +263 -0
- package/templates/storefront-nextjs/app/categories/[slug]/page.tsx +200 -0
- package/templates/storefront-nextjs/app/categories/page.tsx +58 -0
- package/templates/storefront-nextjs/app/checkout/page.tsx +351 -0
- package/templates/storefront-nextjs/app/collections/[slug]/page.tsx +158 -0
- package/templates/storefront-nextjs/app/collections/page.tsx +61 -0
- package/templates/storefront-nextjs/app/globals.css +98 -0
- package/templates/storefront-nextjs/app/layout.tsx +39 -0
- package/templates/storefront-nextjs/app/page.tsx +136 -0
- package/templates/storefront-nextjs/app/products/[slug]/page.tsx +119 -0
- package/templates/storefront-nextjs/app/products/page.tsx +107 -0
- package/templates/storefront-nextjs/app/search/page.tsx +127 -0
- package/templates/storefront-nextjs/components/auth/auth-guard.tsx +94 -0
- package/templates/storefront-nextjs/components/commerce/add-to-cart-button.tsx +77 -0
- package/templates/storefront-nextjs/components/commerce/cart-icon.tsx +29 -0
- package/templates/storefront-nextjs/components/commerce/currency-selector.tsx +217 -0
- package/templates/storefront-nextjs/components/commerce/pagination.tsx +62 -0
- package/templates/storefront-nextjs/components/commerce/product-actions.tsx +135 -0
- package/templates/storefront-nextjs/components/commerce/product-filters.tsx +109 -0
- package/templates/storefront-nextjs/components/commerce/product-price.tsx +375 -0
- package/templates/storefront-nextjs/components/commerce/search-input.tsx +178 -0
- package/templates/storefront-nextjs/components/commerce/sort-select.tsx +64 -0
- package/templates/storefront-nextjs/components/commerce/variant-selector.tsx +210 -0
- package/templates/storefront-nextjs/components/layout/footer.tsx +107 -0
- package/templates/storefront-nextjs/components/layout/header.tsx +104 -0
- package/templates/storefront-nextjs/components/providers.tsx +62 -0
- package/templates/storefront-nextjs/lib/auth/routes.ts +52 -0
- package/templates/storefront-nextjs/lib/currency.tsx +140 -0
- package/templates/storefront-nextjs/lib/format.ts +159 -0
- package/templates/storefront-nextjs/lib/graphql-queries.ts +629 -0
- package/templates/storefront-nextjs/lib/hooks.ts +30 -0
- package/templates/storefront-nextjs/middleware.ts +80 -0
- package/templates/storefront-nextjs/next.config.ts +37 -0
- package/templates/storefront-nextjs/open-next.config.ts +3 -0
- package/templates/storefront-nextjs/package.dev.json +30 -0
- package/templates/storefront-nextjs/package.json +32 -0
- package/templates/storefront-nextjs/package.json.template +32 -0
- package/templates/storefront-nextjs/postcss.config.mjs +8 -0
- package/templates/storefront-nextjs/tailwind.config.ts +111 -0
- package/templates/storefront-nextjs/tsconfig.json +27 -0
- package/templates/storefront-nextjs/wrangler.toml +9 -0
- package/templates/storefront-nextjs-shadcn/.env.example +68 -0
- package/templates/storefront-nextjs-shadcn/.github/workflows/build-template.yml +109 -0
- package/templates/storefront-nextjs-shadcn/.github/workflows/deploy.yml +25 -0
- package/templates/storefront-nextjs-shadcn/.github/workflows/preview.yml +22 -0
- package/templates/storefront-nextjs-shadcn/CART_INTEGRATION.md +282 -0
- package/templates/storefront-nextjs-shadcn/CLAUDE.md +96 -0
- package/templates/storefront-nextjs-shadcn/GRAPHQL_DOCUMENT_NAMES.md +190 -0
- package/templates/storefront-nextjs-shadcn/GRAPHQL_ERROR_HANDLING.md +263 -0
- package/templates/storefront-nextjs-shadcn/GRAPHQL_FIXES_SUMMARY.md +135 -0
- package/templates/storefront-nextjs-shadcn/GRAPHQL_INTEGRATION_COMPLETE.md +142 -0
- package/templates/storefront-nextjs-shadcn/INTEGRATION_CHECKLIST.md +448 -0
- package/templates/storefront-nextjs-shadcn/PRODUCT_DETAIL_PAGE_IMPLEMENTATION.md +307 -0
- package/templates/storefront-nextjs-shadcn/README.md +195 -0
- package/templates/storefront-nextjs-shadcn/THEME_CUSTOMIZATION.md +245 -0
- package/templates/storefront-nextjs-shadcn/app/about/page.tsx +34 -0
- package/templates/storefront-nextjs-shadcn/app/account/addresses/page.tsx +215 -0
- package/templates/storefront-nextjs-shadcn/app/account/loyalty/page.tsx +484 -0
- package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/page.tsx +128 -0
- package/templates/storefront-nextjs-shadcn/app/account/orders/[id]/tracking/page.tsx +206 -0
- package/templates/storefront-nextjs-shadcn/app/account/orders/page.tsx +80 -0
- package/templates/storefront-nextjs-shadcn/app/account/page.tsx +107 -0
- package/templates/storefront-nextjs-shadcn/app/account/settings/page.tsx +195 -0
- package/templates/storefront-nextjs-shadcn/app/api/auth/clear-token/route.ts +87 -0
- package/templates/storefront-nextjs-shadcn/app/api/auth/set-token/route.ts +125 -0
- package/templates/storefront-nextjs-shadcn/app/auth/forgot-password/page.tsx +131 -0
- package/templates/storefront-nextjs-shadcn/app/auth/login/page.tsx +24 -0
- package/templates/storefront-nextjs-shadcn/app/auth/register/page.tsx +20 -0
- package/templates/storefront-nextjs-shadcn/app/blog/[slug]/page.tsx +323 -0
- package/templates/storefront-nextjs-shadcn/app/blog/page.tsx +159 -0
- package/templates/storefront-nextjs-shadcn/app/brands/[slug]/page.tsx +170 -0
- package/templates/storefront-nextjs-shadcn/app/brands/page.tsx +73 -0
- package/templates/storefront-nextjs-shadcn/app/cart/page.tsx +165 -0
- package/templates/storefront-nextjs-shadcn/app/categories/[slug]/page.tsx +78 -0
- package/templates/storefront-nextjs-shadcn/app/categories/page.tsx +75 -0
- package/templates/storefront-nextjs-shadcn/app/checkout/page.tsx +1752 -0
- package/templates/storefront-nextjs-shadcn/app/checkout/success/[orderId]/page.tsx +256 -0
- package/templates/storefront-nextjs-shadcn/app/collections/[handle]/page.tsx +74 -0
- package/templates/storefront-nextjs-shadcn/app/collections/page.tsx +75 -0
- package/templates/storefront-nextjs-shadcn/app/contact/page.tsx +114 -0
- package/templates/storefront-nextjs-shadcn/app/error.tsx +90 -0
- package/templates/storefront-nextjs-shadcn/app/globals.css +125 -0
- package/templates/storefront-nextjs-shadcn/app/layout.tsx +57 -0
- package/templates/storefront-nextjs-shadcn/app/not-found.tsx +68 -0
- package/templates/storefront-nextjs-shadcn/app/page.tsx +21 -0
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/page.tsx +246 -0
- package/templates/storefront-nextjs-shadcn/app/products/[slug]/product-client.tsx +343 -0
- package/templates/storefront-nextjs-shadcn/app/products/page.tsx +25 -0
- package/templates/storefront-nextjs-shadcn/app/products/products-client.tsx +192 -0
- package/templates/storefront-nextjs-shadcn/app/returns/page.tsx +77 -0
- package/templates/storefront-nextjs-shadcn/app/robots.ts +53 -0
- package/templates/storefront-nextjs-shadcn/app/search/page.tsx +16 -0
- package/templates/storefront-nextjs-shadcn/app/search/search-client.tsx +47 -0
- package/templates/storefront-nextjs-shadcn/app/shipping/page.tsx +62 -0
- package/templates/storefront-nextjs-shadcn/app/sitemap.ts +144 -0
- package/templates/storefront-nextjs-shadcn/app/wishlist/page.tsx +179 -0
- package/templates/storefront-nextjs-shadcn/codegen.ts +51 -0
- package/templates/storefront-nextjs-shadcn/components/account/address-form.tsx +348 -0
- package/templates/storefront-nextjs-shadcn/components/account/address-list.tsx +144 -0
- package/templates/storefront-nextjs-shadcn/components/account/order-details.tsx +258 -0
- package/templates/storefront-nextjs-shadcn/components/account/order-history.tsx +107 -0
- package/templates/storefront-nextjs-shadcn/components/auth/account-menu.tsx +132 -0
- package/templates/storefront-nextjs-shadcn/components/auth/login-form.tsx +188 -0
- package/templates/storefront-nextjs-shadcn/components/auth/register-form.tsx +305 -0
- package/templates/storefront-nextjs-shadcn/components/blog/blog-card.tsx +240 -0
- package/templates/storefront-nextjs-shadcn/components/blog/blog-sidebar.tsx +177 -0
- package/templates/storefront-nextjs-shadcn/components/blog/index.ts +8 -0
- package/templates/storefront-nextjs-shadcn/components/brand/brand-card.tsx +119 -0
- package/templates/storefront-nextjs-shadcn/components/brand/brand-grid.tsx +64 -0
- package/templates/storefront-nextjs-shadcn/components/cart/cart-drawer.tsx +140 -0
- package/templates/storefront-nextjs-shadcn/components/cart/cart-icon.tsx +48 -0
- package/templates/storefront-nextjs-shadcn/components/cart/cart-item.tsx +112 -0
- package/templates/storefront-nextjs-shadcn/components/cart/cart-summary.tsx +84 -0
- package/templates/storefront-nextjs-shadcn/components/cart/index.ts +17 -0
- package/templates/storefront-nextjs-shadcn/components/cart/promo-code-input.tsx +121 -0
- package/templates/storefront-nextjs-shadcn/components/cart/shipping-estimator.tsx +162 -0
- package/templates/storefront-nextjs-shadcn/components/checkout/index.ts +25 -0
- package/templates/storefront-nextjs-shadcn/components/checkout/payment-method-card.tsx +187 -0
- package/templates/storefront-nextjs-shadcn/components/checkout/payment-step.tsx +160 -0
- package/templates/storefront-nextjs-shadcn/components/checkout/tax-breakdown.tsx +154 -0
- package/templates/storefront-nextjs-shadcn/components/commerce/currency-selector.tsx +225 -0
- package/templates/storefront-nextjs-shadcn/components/commerce/pagination.tsx +62 -0
- package/templates/storefront-nextjs-shadcn/components/commerce/product-actions.tsx +158 -0
- package/templates/storefront-nextjs-shadcn/components/commerce/search-input.tsx +174 -0
- package/templates/storefront-nextjs-shadcn/components/commerce/variant-selector.tsx +210 -0
- package/templates/storefront-nextjs-shadcn/components/common/category-card.tsx +97 -0
- package/templates/storefront-nextjs-shadcn/components/common/collection-card.tsx +187 -0
- package/templates/storefront-nextjs-shadcn/components/common/price-display.tsx +151 -0
- package/templates/storefront-nextjs-shadcn/components/common/social-share.tsx +166 -0
- package/templates/storefront-nextjs-shadcn/components/discount/discount-breakdown.tsx +245 -0
- package/templates/storefront-nextjs-shadcn/components/discount/discount-code-input.tsx +246 -0
- package/templates/storefront-nextjs-shadcn/components/discount/index.ts +19 -0
- package/templates/storefront-nextjs-shadcn/components/error/error-boundary.tsx +113 -0
- package/templates/storefront-nextjs-shadcn/components/error/index.ts +7 -0
- package/templates/storefront-nextjs-shadcn/components/filters/attribute-filter.tsx +153 -0
- package/templates/storefront-nextjs-shadcn/components/filters/checkbox-group-filter.tsx +167 -0
- package/templates/storefront-nextjs-shadcn/components/filters/color-swatch-filter.tsx +176 -0
- package/templates/storefront-nextjs-shadcn/components/filters/dynamic-attribute-filters.tsx +220 -0
- package/templates/storefront-nextjs-shadcn/components/filters/index.ts +36 -0
- package/templates/storefront-nextjs-shadcn/components/filters/range-slider-filter.tsx +193 -0
- package/templates/storefront-nextjs-shadcn/components/filters/toggle-filter.tsx +132 -0
- package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-balance.tsx +321 -0
- package/templates/storefront-nextjs-shadcn/components/gift-card/gift-card-input.tsx +309 -0
- package/templates/storefront-nextjs-shadcn/components/gift-card/index.ts +24 -0
- package/templates/storefront-nextjs-shadcn/components/home/category-grid.tsx +72 -0
- package/templates/storefront-nextjs-shadcn/components/home/featured-collections.tsx +107 -0
- package/templates/storefront-nextjs-shadcn/components/home/featured-products.tsx +85 -0
- package/templates/storefront-nextjs-shadcn/components/home/hero-section.tsx +34 -0
- package/templates/storefront-nextjs-shadcn/components/home/index.ts +8 -0
- package/templates/storefront-nextjs-shadcn/components/home/newsletter-signup.tsx +108 -0
- package/templates/storefront-nextjs-shadcn/components/layout/breadcrumbs.tsx +133 -0
- package/templates/storefront-nextjs-shadcn/components/layout/currency-selector.tsx +341 -0
- package/templates/storefront-nextjs-shadcn/components/layout/footer.tsx +128 -0
- package/templates/storefront-nextjs-shadcn/components/layout/header.tsx +147 -0
- package/templates/storefront-nextjs-shadcn/components/layout/index.ts +9 -0
- package/templates/storefront-nextjs-shadcn/components/layout/mobile-menu.tsx +211 -0
- package/templates/storefront-nextjs-shadcn/components/layout/navigation.tsx +95 -0
- package/templates/storefront-nextjs-shadcn/components/layout/theme-switcher.tsx +192 -0
- package/templates/storefront-nextjs-shadcn/components/loyalty/index.ts +11 -0
- package/templates/storefront-nextjs-shadcn/components/loyalty/points-balance.tsx +93 -0
- package/templates/storefront-nextjs-shadcn/components/loyalty/points-history.tsx +177 -0
- package/templates/storefront-nextjs-shadcn/components/loyalty/referral-section.tsx +250 -0
- package/templates/storefront-nextjs-shadcn/components/loyalty/rewards-catalog.tsx +217 -0
- package/templates/storefront-nextjs-shadcn/components/loyalty/tier-badge.tsx +106 -0
- package/templates/storefront-nextjs-shadcn/components/loyalty/tier-progress.tsx +131 -0
- package/templates/storefront-nextjs-shadcn/components/order/delivery-estimate.tsx +196 -0
- package/templates/storefront-nextjs-shadcn/components/order/index.ts +11 -0
- package/templates/storefront-nextjs-shadcn/components/order/order-tracking.tsx +200 -0
- package/templates/storefront-nextjs-shadcn/components/order/shipment-card.tsx +407 -0
- package/templates/storefront-nextjs-shadcn/components/order/tracking-status.tsx +222 -0
- package/templates/storefront-nextjs-shadcn/components/order/tracking-timeline.tsx +205 -0
- package/templates/storefront-nextjs-shadcn/components/product/add-to-cart-button.tsx +161 -0
- package/templates/storefront-nextjs-shadcn/components/product/b2b-price-display.tsx +250 -0
- package/templates/storefront-nextjs-shadcn/components/product/discount-badge.tsx +196 -0
- package/templates/storefront-nextjs-shadcn/components/product/index.ts +41 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-card.tsx +147 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-filters.tsx +217 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-gallery.tsx +143 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-grid.tsx +83 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-image.tsx +155 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-price.tsx +158 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-quantity-selector.tsx +111 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-reviews.tsx +238 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-sort.tsx +58 -0
- package/templates/storefront-nextjs-shadcn/components/product/product-variant-selector.tsx +169 -0
- package/templates/storefront-nextjs-shadcn/components/product/review-card.tsx +220 -0
- package/templates/storefront-nextjs-shadcn/components/product/review-form.tsx +338 -0
- package/templates/storefront-nextjs-shadcn/components/product/review-summary.tsx +143 -0
- package/templates/storefront-nextjs-shadcn/components/product/sale-countdown.tsx +166 -0
- package/templates/storefront-nextjs-shadcn/components/product/savings-display.tsx +213 -0
- package/templates/storefront-nextjs-shadcn/components/product/similar-products.tsx +57 -0
- package/templates/storefront-nextjs-shadcn/components/product/stock-indicator.tsx +91 -0
- package/templates/storefront-nextjs-shadcn/components/providers/currency-provider.tsx +103 -0
- package/templates/storefront-nextjs-shadcn/components/providers/index.ts +8 -0
- package/templates/storefront-nextjs-shadcn/components/providers/query-provider.tsx +260 -0
- package/templates/storefront-nextjs-shadcn/components/providers/theme-provider.tsx +13 -0
- package/templates/storefront-nextjs-shadcn/components/returns/index.ts +26 -0
- package/templates/storefront-nextjs-shadcn/components/returns/return-request-form.tsx +608 -0
- package/templates/storefront-nextjs-shadcn/components/returns/return-status-card.tsx +554 -0
- package/templates/storefront-nextjs-shadcn/components/search/index.ts +8 -0
- package/templates/storefront-nextjs-shadcn/components/search/search-bar.tsx +140 -0
- package/templates/storefront-nextjs-shadcn/components/search/search-results.tsx +58 -0
- package/templates/storefront-nextjs-shadcn/components/search/search-suggestions.tsx +43 -0
- package/templates/storefront-nextjs-shadcn/components/seo/index.ts +12 -0
- package/templates/storefront-nextjs-shadcn/components/seo/json-ld.tsx +56 -0
- package/templates/storefront-nextjs-shadcn/components/seo/product-json-ld.ts +167 -0
- package/templates/storefront-nextjs-shadcn/components/shipping/index.ts +16 -0
- package/templates/storefront-nextjs-shadcn/components/shipping/shipping-method-selector.tsx +337 -0
- package/templates/storefront-nextjs-shadcn/components/ui/accordion.tsx +153 -0
- package/templates/storefront-nextjs-shadcn/components/ui/alert.tsx +59 -0
- package/templates/storefront-nextjs-shadcn/components/ui/badge.tsx +34 -0
- package/templates/storefront-nextjs-shadcn/components/ui/button.tsx +51 -0
- package/templates/storefront-nextjs-shadcn/components/ui/card.tsx +77 -0
- package/templates/storefront-nextjs-shadcn/components/ui/checkbox.tsx +30 -0
- package/templates/storefront-nextjs-shadcn/components/ui/dialog.tsx +137 -0
- package/templates/storefront-nextjs-shadcn/components/ui/empty-state.tsx +207 -0
- package/templates/storefront-nextjs-shadcn/components/ui/index.ts +67 -0
- package/templates/storefront-nextjs-shadcn/components/ui/input.tsx +65 -0
- package/templates/storefront-nextjs-shadcn/components/ui/label.tsx +26 -0
- package/templates/storefront-nextjs-shadcn/components/ui/pagination.tsx +205 -0
- package/templates/storefront-nextjs-shadcn/components/ui/radio-group.tsx +44 -0
- package/templates/storefront-nextjs-shadcn/components/ui/select.tsx +160 -0
- package/templates/storefront-nextjs-shadcn/components/ui/separator.tsx +28 -0
- package/templates/storefront-nextjs-shadcn/components/ui/skeleton.tsx +20 -0
- package/templates/storefront-nextjs-shadcn/components/ui/spinner.tsx +82 -0
- package/templates/storefront-nextjs-shadcn/components/ui/tabs.tsx +119 -0
- package/templates/storefront-nextjs-shadcn/components/ui/toast.tsx +96 -0
- package/templates/storefront-nextjs-shadcn/components/wishlist/index.ts +9 -0
- package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-button.tsx +148 -0
- package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-icon.tsx +47 -0
- package/templates/storefront-nextjs-shadcn/components/wishlist/wishlist-item.tsx +165 -0
- package/templates/storefront-nextjs-shadcn/components.json +19 -0
- package/templates/storefront-nextjs-shadcn/generated/.gitkeep +2 -0
- package/templates/storefront-nextjs-shadcn/graphql/.gitkeep +31 -0
- package/templates/storefront-nextjs-shadcn/graphql/collections.example.ts +168 -0
- package/templates/storefront-nextjs-shadcn/graphql/products.example.ts +160 -0
- package/templates/storefront-nextjs-shadcn/hooks/index.ts +9 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-auth.ts +310 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-cart-actions.ts +286 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-cart-sync.ts +110 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-filter-params.test.ts +173 -0
- package/templates/storefront-nextjs-shadcn/hooks/use-filter-params.ts +298 -0
- package/templates/storefront-nextjs-shadcn/lib/auth/cookies.ts +220 -0
- package/templates/storefront-nextjs-shadcn/lib/auth/routes.ts +57 -0
- package/templates/storefront-nextjs-shadcn/lib/config.ts +46 -0
- package/templates/storefront-nextjs-shadcn/lib/currency/IMPLEMENTATION_SUMMARY.md +254 -0
- package/templates/storefront-nextjs-shadcn/lib/currency/README.md +464 -0
- package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.test.ts +328 -0
- package/templates/storefront-nextjs-shadcn/lib/currency/cookie-manager.ts +295 -0
- package/templates/storefront-nextjs-shadcn/lib/currency/index.ts +27 -0
- package/templates/storefront-nextjs-shadcn/lib/format.test.ts +397 -0
- package/templates/storefront-nextjs-shadcn/lib/format.ts +226 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/client.ts +109 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/hooks.ts +1183 -0
- package/templates/storefront-nextjs-shadcn/lib/graphql/server.ts +267 -0
- package/templates/storefront-nextjs-shadcn/lib/hooks.ts +30 -0
- package/templates/storefront-nextjs-shadcn/lib/theme/theme-config.ts +89 -0
- package/templates/storefront-nextjs-shadcn/lib/utils.ts +6 -0
- package/templates/storefront-nextjs-shadcn/next.config.ts +47 -0
- package/templates/storefront-nextjs-shadcn/open-next.config.ts +3 -0
- package/templates/storefront-nextjs-shadcn/package.dev.json +30 -0
- package/templates/storefront-nextjs-shadcn/package.json +60 -0
- package/templates/storefront-nextjs-shadcn/package.json.template +46 -0
- package/templates/storefront-nextjs-shadcn/postcss.config.mjs +8 -0
- package/templates/storefront-nextjs-shadcn/proxy.ts +80 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/apple-pay.svg +8 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/bank-transfer.svg +10 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/blik.svg +6 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/cash-on-delivery.svg +11 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/google-pay.svg +11 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/mastercard.svg +7 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/paypal.svg +7 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/payu.svg +7 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/przelewy24.svg +7 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/stripe.svg +4 -0
- package/templates/storefront-nextjs-shadcn/public/icons/payment/visa.svg +5 -0
- package/templates/storefront-nextjs-shadcn/stores/auth-store.ts +66 -0
- package/templates/storefront-nextjs-shadcn/stores/cart-store.ts +56 -0
- package/templates/storefront-nextjs-shadcn/stores/checkout-store.ts +184 -0
- package/templates/storefront-nextjs-shadcn/stores/currency-store.ts +103 -0
- package/templates/storefront-nextjs-shadcn/stores/wishlist-store.ts +291 -0
- package/templates/storefront-nextjs-shadcn/tailwind.config.ts +111 -0
- package/templates/storefront-nextjs-shadcn/tsconfig.json +27 -0
- package/templates/storefront-nextjs-shadcn/wrangler.toml +9 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import Link from "next/link";
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
import { useCollections } from "@/lib/graphql/hooks";
|
|
6
|
+
|
|
7
|
+
export interface CategoryGridProps {
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function CategoryGrid({ className }: CategoryGridProps) {
|
|
12
|
+
// Use collections for homepage marketing (not categories)
|
|
13
|
+
// Collections are better for homepage because they're curated and flexible
|
|
14
|
+
const { data, isLoading, error } = useCollections({
|
|
15
|
+
first: 8,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const collections = data?.collections ?? [];
|
|
19
|
+
|
|
20
|
+
if (isLoading) {
|
|
21
|
+
return (
|
|
22
|
+
<section className={cn("container mx-auto px-4", className)}>
|
|
23
|
+
<div className="mb-8 text-center">
|
|
24
|
+
<h2 className="text-3xl font-bold text-foreground">Shop by Category</h2>
|
|
25
|
+
<p className="mt-2 text-muted-foreground">
|
|
26
|
+
Find exactly what you're looking for
|
|
27
|
+
</p>
|
|
28
|
+
</div>
|
|
29
|
+
<div className="grid grid-cols-2 gap-4 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-4">
|
|
30
|
+
{Array.from({ length: 8 }).map((_, i) => (
|
|
31
|
+
<div key={i} className="animate-pulse rounded-lg border border-border p-6">
|
|
32
|
+
<div className="mb-3 h-10 w-10 bg-muted rounded mx-auto"></div>
|
|
33
|
+
<div className="h-4 bg-muted rounded"></div>
|
|
34
|
+
</div>
|
|
35
|
+
))}
|
|
36
|
+
</div>
|
|
37
|
+
</section>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (error || collections.length === 0) {
|
|
42
|
+
return null; // Don't show section if no collections
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<section className={cn("container mx-auto px-4", className)}>
|
|
47
|
+
<div className="mb-8 text-center">
|
|
48
|
+
<h2 className="text-3xl font-bold text-foreground">Shop by Category</h2>
|
|
49
|
+
<p className="mt-2 text-muted-foreground">
|
|
50
|
+
Find exactly what you're looking for
|
|
51
|
+
</p>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<div className="grid grid-cols-2 gap-4 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-4">
|
|
55
|
+
{collections.map((collection: any) => (
|
|
56
|
+
<Link
|
|
57
|
+
key={collection.id}
|
|
58
|
+
href={`/collections/${collection.handle}`}
|
|
59
|
+
className="group flex flex-col items-center justify-center rounded-lg border border-border bg-background p-6 transition-all hover:border-primary hover:shadow-md"
|
|
60
|
+
>
|
|
61
|
+
<div className="mb-3 text-4xl transition-transform group-hover:scale-110">
|
|
62
|
+
🛍️
|
|
63
|
+
</div>
|
|
64
|
+
<span className="text-center font-medium text-foreground group-hover:text-primary">
|
|
65
|
+
{collection.title}
|
|
66
|
+
</span>
|
|
67
|
+
</Link>
|
|
68
|
+
))}
|
|
69
|
+
</div>
|
|
70
|
+
</section>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import Link from "next/link";
|
|
4
|
+
import { Button } from "@/components/ui/button";
|
|
5
|
+
import { Card, CardContent } from "@/components/ui/card";
|
|
6
|
+
import { useCollections } from "@/lib/graphql/hooks";
|
|
7
|
+
|
|
8
|
+
export interface Collection {
|
|
9
|
+
id: string;
|
|
10
|
+
handle: string;
|
|
11
|
+
title: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
image?: {
|
|
14
|
+
url: string;
|
|
15
|
+
altText?: string | null;
|
|
16
|
+
} | null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function FeaturedCollections() {
|
|
20
|
+
// Fetch collections using GraphQL
|
|
21
|
+
const { data, isLoading, error } = useCollections({
|
|
22
|
+
first: 3,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const collections = data?.collections ?? [];
|
|
26
|
+
|
|
27
|
+
if (isLoading) {
|
|
28
|
+
return (
|
|
29
|
+
<section className="container mx-auto px-4">
|
|
30
|
+
<div className="mb-8 text-center">
|
|
31
|
+
<h2 className="text-3xl font-bold text-foreground">Featured Collections</h2>
|
|
32
|
+
<p className="mt-2 text-muted-foreground">
|
|
33
|
+
Explore our curated collections
|
|
34
|
+
</p>
|
|
35
|
+
</div>
|
|
36
|
+
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
|
|
37
|
+
{Array.from({ length: 3 }).map((_, i) => (
|
|
38
|
+
<div key={i} className="animate-pulse">
|
|
39
|
+
<div className="aspect-[4/3] bg-muted rounded-lg mb-4"></div>
|
|
40
|
+
<div className="h-6 bg-muted rounded mb-2"></div>
|
|
41
|
+
<div className="h-4 bg-muted rounded w-3/4"></div>
|
|
42
|
+
</div>
|
|
43
|
+
))}
|
|
44
|
+
</div>
|
|
45
|
+
</section>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (error || collections.length === 0) {
|
|
50
|
+
return null; // Don't show section if no collections
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<section className="container mx-auto px-4">
|
|
55
|
+
<div className="mb-8 text-center">
|
|
56
|
+
<h2 className="text-3xl font-bold text-foreground">Featured Collections</h2>
|
|
57
|
+
<p className="mt-2 text-muted-foreground">
|
|
58
|
+
Explore our curated collections
|
|
59
|
+
</p>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
{collections.length > 0 ? (
|
|
63
|
+
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
|
64
|
+
{collections.map((collection: Collection) => (
|
|
65
|
+
<Link
|
|
66
|
+
key={collection.id}
|
|
67
|
+
href={`/collections/${collection.handle}`}
|
|
68
|
+
className="group"
|
|
69
|
+
>
|
|
70
|
+
<Card className="overflow-hidden transition-shadow hover:shadow-lg">
|
|
71
|
+
<div className="relative aspect-[16/9] overflow-hidden bg-muted">
|
|
72
|
+
{collection.image?.url ? (
|
|
73
|
+
<img
|
|
74
|
+
src={collection.image.url}
|
|
75
|
+
alt={collection.image.altText || collection.title}
|
|
76
|
+
className="h-full w-full object-cover transition-transform duration-300 group-hover:scale-105"
|
|
77
|
+
/>
|
|
78
|
+
) : (
|
|
79
|
+
<div className="flex h-full items-center justify-center text-muted-foreground">
|
|
80
|
+
<span className="text-4xl">🛍️</span>
|
|
81
|
+
</div>
|
|
82
|
+
)}
|
|
83
|
+
</div>
|
|
84
|
+
<CardContent className="p-6">
|
|
85
|
+
<h3 className="text-xl font-semibold text-foreground group-hover:text-primary">
|
|
86
|
+
{collection.title}
|
|
87
|
+
</h3>
|
|
88
|
+
{collection.description && (
|
|
89
|
+
<p className="mt-2 line-clamp-2 text-sm text-muted-foreground">
|
|
90
|
+
{collection.description}
|
|
91
|
+
</p>
|
|
92
|
+
)}
|
|
93
|
+
</CardContent>
|
|
94
|
+
</Card>
|
|
95
|
+
</Link>
|
|
96
|
+
))}
|
|
97
|
+
</div>
|
|
98
|
+
) : (
|
|
99
|
+
<div className="rounded-lg border border-border bg-muted/50 p-12 text-center">
|
|
100
|
+
<p className="text-muted-foreground">
|
|
101
|
+
No collections available at the moment.
|
|
102
|
+
</p>
|
|
103
|
+
</div>
|
|
104
|
+
)}
|
|
105
|
+
</section>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import Link from "next/link";
|
|
4
|
+
import { ProductGrid } from "@/components/product/product-grid";
|
|
5
|
+
import { Button } from "@/components/ui/button";
|
|
6
|
+
import { useProducts } from "@/lib/graphql/hooks";
|
|
7
|
+
|
|
8
|
+
export function FeaturedProducts() {
|
|
9
|
+
// Fetch featured products using GraphQL
|
|
10
|
+
const { data, isLoading, error } = useProducts({
|
|
11
|
+
first: 8,
|
|
12
|
+
// TODO: Add featured filter when backend supports it
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const products = data?.products ?? [];
|
|
16
|
+
|
|
17
|
+
if (isLoading) {
|
|
18
|
+
return (
|
|
19
|
+
<section className="container mx-auto px-4">
|
|
20
|
+
<div className="mb-8 flex items-center justify-between">
|
|
21
|
+
<div>
|
|
22
|
+
<h2 className="text-3xl font-bold text-foreground">Featured Products</h2>
|
|
23
|
+
<p className="mt-2 text-muted-foreground">
|
|
24
|
+
Handpicked favorites just for you
|
|
25
|
+
</p>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4">
|
|
29
|
+
{Array.from({ length: 4 }).map((_, i) => (
|
|
30
|
+
<div key={i} className="animate-pulse">
|
|
31
|
+
<div className="aspect-square bg-muted rounded-lg mb-4"></div>
|
|
32
|
+
<div className="h-4 bg-muted rounded mb-2"></div>
|
|
33
|
+
<div className="h-4 bg-muted rounded w-1/2"></div>
|
|
34
|
+
</div>
|
|
35
|
+
))}
|
|
36
|
+
</div>
|
|
37
|
+
</section>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Handle error state explicitly
|
|
42
|
+
if (error) {
|
|
43
|
+
console.error('[FeaturedProducts] Failed to load products:', error);
|
|
44
|
+
return null; // Gracefully hide section on error
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Hide section if no products
|
|
48
|
+
if (products.length === 0) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<section className="container mx-auto px-4">
|
|
54
|
+
<div className="mb-8 flex items-center justify-between">
|
|
55
|
+
<div>
|
|
56
|
+
<h2 className="text-3xl font-bold text-foreground">Featured Products</h2>
|
|
57
|
+
<p className="mt-2 text-muted-foreground">
|
|
58
|
+
Handpicked favorites just for you
|
|
59
|
+
</p>
|
|
60
|
+
</div>
|
|
61
|
+
<Button variant="outline" asChild>
|
|
62
|
+
<Link href="/products">View All</Link>
|
|
63
|
+
</Button>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
{products.length > 0 ? (
|
|
67
|
+
<ProductGrid
|
|
68
|
+
products={products}
|
|
69
|
+
columns={4}
|
|
70
|
+
priorityCount={4}
|
|
71
|
+
showBadges
|
|
72
|
+
/>
|
|
73
|
+
) : (
|
|
74
|
+
<div className="rounded-lg border border-border bg-muted/50 p-12 text-center">
|
|
75
|
+
<p className="text-muted-foreground">
|
|
76
|
+
No featured products available at the moment.
|
|
77
|
+
</p>
|
|
78
|
+
<Button className="mt-4" asChild>
|
|
79
|
+
<Link href="/products">Browse All Products</Link>
|
|
80
|
+
</Button>
|
|
81
|
+
</div>
|
|
82
|
+
)}
|
|
83
|
+
</section>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import Link from "next/link";
|
|
2
|
+
import { Button } from "@/components/ui/button";
|
|
3
|
+
|
|
4
|
+
export function HeroSection() {
|
|
5
|
+
return (
|
|
6
|
+
<section className="container mx-auto px-4">
|
|
7
|
+
<div className="relative overflow-hidden rounded-2xl bg-gradient-to-r from-primary/10 via-primary/5 to-background p-8 md:p-16">
|
|
8
|
+
<div className="relative z-10 mx-auto max-w-3xl text-center">
|
|
9
|
+
<h1 className="mb-4 text-4xl font-bold tracking-tight text-foreground sm:text-5xl md:text-6xl">
|
|
10
|
+
Welcome to{" "}
|
|
11
|
+
<span className="text-primary">
|
|
12
|
+
{process.env.NEXT_PUBLIC_SITE_NAME || "My Store"}
|
|
13
|
+
</span>
|
|
14
|
+
</h1>
|
|
15
|
+
<p className="mx-auto mb-8 max-w-2xl text-lg text-muted-foreground">
|
|
16
|
+
Discover our curated collection of quality products. Shop with confidence and enjoy exceptional service.
|
|
17
|
+
</p>
|
|
18
|
+
<div className="flex flex-col justify-center gap-4 sm:flex-row">
|
|
19
|
+
<Button size="lg" asChild>
|
|
20
|
+
<Link href="/products">Shop Now</Link>
|
|
21
|
+
</Button>
|
|
22
|
+
<Button size="lg" variant="outline" asChild>
|
|
23
|
+
<Link href="/products">Browse Products</Link>
|
|
24
|
+
</Button>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
{/* Decorative elements */}
|
|
29
|
+
<div className="absolute -right-20 -top-20 h-64 w-64 rounded-full bg-primary/10 blur-3xl" />
|
|
30
|
+
<div className="absolute -bottom-20 -left-20 h-64 w-64 rounded-full bg-primary/10 blur-3xl" />
|
|
31
|
+
</div>
|
|
32
|
+
</section>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { HeroSection } from './hero-section';
|
|
2
|
+
export { FeaturedProducts } from './featured-products';
|
|
3
|
+
export { FeaturedCollections } from './featured-collections';
|
|
4
|
+
export type { Collection } from './featured-collections';
|
|
5
|
+
export { CategoryGrid } from './category-grid';
|
|
6
|
+
export type { CategoryGridProps } from './category-grid';
|
|
7
|
+
export { NewsletterSignup } from './newsletter-signup';
|
|
8
|
+
export type { NewsletterSignupProps } from './newsletter-signup';
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { Mail, Check } from "lucide-react";
|
|
5
|
+
import { Input } from "@/components/ui/input";
|
|
6
|
+
import { Button } from "@/components/ui/button";
|
|
7
|
+
import { cn } from "@/lib/utils";
|
|
8
|
+
|
|
9
|
+
export interface NewsletterSignupProps {
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function NewsletterSignup({ className }: NewsletterSignupProps) {
|
|
14
|
+
const [email, setEmail] = useState("");
|
|
15
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
16
|
+
const [isSuccess, setIsSuccess] = useState(false);
|
|
17
|
+
const [error, setError] = useState<string | null>(null);
|
|
18
|
+
|
|
19
|
+
const handleSubmit = async (e: React.FormEvent) => {
|
|
20
|
+
e.preventDefault();
|
|
21
|
+
|
|
22
|
+
if (!email || !email.includes("@")) {
|
|
23
|
+
setError("Please enter a valid email address");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
setIsLoading(true);
|
|
28
|
+
setError(null);
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
// TODO: Implement newsletter subscription API call
|
|
32
|
+
// await subscribeToNewsletter(email);
|
|
33
|
+
|
|
34
|
+
// Simulate API call
|
|
35
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
36
|
+
|
|
37
|
+
setIsSuccess(true);
|
|
38
|
+
setEmail("");
|
|
39
|
+
|
|
40
|
+
// Reset success state after 3 seconds
|
|
41
|
+
setTimeout(() => {
|
|
42
|
+
setIsSuccess(false);
|
|
43
|
+
}, 3000);
|
|
44
|
+
} catch (err) {
|
|
45
|
+
setError("Failed to subscribe. Please try again.");
|
|
46
|
+
} finally {
|
|
47
|
+
setIsLoading(false);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<section className={cn("container mx-auto px-4", className)}>
|
|
53
|
+
<div className="rounded-2xl bg-gradient-to-r from-primary/10 via-primary/5 to-background p-8 md:p-12">
|
|
54
|
+
<div className="mx-auto max-w-2xl text-center">
|
|
55
|
+
<div className="mb-4 inline-flex h-12 w-12 items-center justify-center rounded-full bg-primary/10">
|
|
56
|
+
<Mail className="h-6 w-6 text-primary" />
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<h2 className="mb-2 text-3xl font-bold text-foreground">
|
|
60
|
+
Stay in the Loop
|
|
61
|
+
</h2>
|
|
62
|
+
<p className="mb-6 text-muted-foreground">
|
|
63
|
+
Subscribe to our newsletter for exclusive offers, new arrivals, and insider news.
|
|
64
|
+
</p>
|
|
65
|
+
|
|
66
|
+
{isSuccess ? (
|
|
67
|
+
<div className="flex items-center justify-center gap-2 rounded-lg bg-green-50 p-4 text-green-700 dark:bg-green-950 dark:text-green-400">
|
|
68
|
+
<Check className="h-5 w-5" />
|
|
69
|
+
<span className="font-medium">
|
|
70
|
+
Thanks for subscribing! Check your email for confirmation.
|
|
71
|
+
</span>
|
|
72
|
+
</div>
|
|
73
|
+
) : (
|
|
74
|
+
<form onSubmit={handleSubmit} className="mx-auto max-w-md">
|
|
75
|
+
<div className="flex flex-col gap-3 sm:flex-row">
|
|
76
|
+
<Input
|
|
77
|
+
type="email"
|
|
78
|
+
placeholder="Enter your email"
|
|
79
|
+
value={email}
|
|
80
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
81
|
+
disabled={isLoading}
|
|
82
|
+
className="flex-1"
|
|
83
|
+
required
|
|
84
|
+
/>
|
|
85
|
+
<Button
|
|
86
|
+
type="submit"
|
|
87
|
+
disabled={isLoading || !email}
|
|
88
|
+
size="lg"
|
|
89
|
+
className="sm:w-auto"
|
|
90
|
+
>
|
|
91
|
+
{isLoading ? "Subscribing..." : "Subscribe"}
|
|
92
|
+
</Button>
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
{error && (
|
|
96
|
+
<p className="mt-2 text-sm text-destructive">{error}</p>
|
|
97
|
+
)}
|
|
98
|
+
|
|
99
|
+
<p className="mt-3 text-xs text-muted-foreground">
|
|
100
|
+
By subscribing, you agree to our Privacy Policy and consent to receive updates.
|
|
101
|
+
</p>
|
|
102
|
+
</form>
|
|
103
|
+
)}
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
</section>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import Link from "next/link";
|
|
4
|
+
import { usePathname } from "next/navigation";
|
|
5
|
+
import { ChevronRight, Home } from "lucide-react";
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
7
|
+
|
|
8
|
+
export interface BreadcrumbItem {
|
|
9
|
+
label: string;
|
|
10
|
+
href: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface BreadcrumbsProps {
|
|
14
|
+
items?: BreadcrumbItem[];
|
|
15
|
+
className?: string;
|
|
16
|
+
showHome?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Breadcrumbs component for navigation hierarchy
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* // Auto-generate from pathname
|
|
24
|
+
* <Breadcrumbs />
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* // Custom breadcrumb items
|
|
28
|
+
* <Breadcrumbs items={[
|
|
29
|
+
* { label: "Products", href: "/products" },
|
|
30
|
+
* { label: "Electronics", href: "/products/electronics" },
|
|
31
|
+
* { label: "Laptops", href: "/products/electronics/laptops" }
|
|
32
|
+
* ]} />
|
|
33
|
+
*/
|
|
34
|
+
export function Breadcrumbs({
|
|
35
|
+
items,
|
|
36
|
+
className,
|
|
37
|
+
showHome = true,
|
|
38
|
+
}: BreadcrumbsProps) {
|
|
39
|
+
const pathname = usePathname();
|
|
40
|
+
|
|
41
|
+
// Auto-generate breadcrumbs from pathname if items not provided
|
|
42
|
+
const breadcrumbItems = items || generateBreadcrumbs(pathname);
|
|
43
|
+
|
|
44
|
+
// Don't show breadcrumbs on homepage
|
|
45
|
+
if (pathname === "/" || breadcrumbItems.length === 0) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<nav
|
|
51
|
+
aria-label="Breadcrumb"
|
|
52
|
+
className={cn("flex items-center gap-2 text-sm", className)}
|
|
53
|
+
>
|
|
54
|
+
<ol className="flex items-center gap-2">
|
|
55
|
+
{showHome && (
|
|
56
|
+
<li>
|
|
57
|
+
<Link
|
|
58
|
+
href="/"
|
|
59
|
+
className="flex items-center text-muted-foreground hover:text-foreground transition-colors"
|
|
60
|
+
aria-label="Home"
|
|
61
|
+
>
|
|
62
|
+
<Home className="h-4 w-4" />
|
|
63
|
+
</Link>
|
|
64
|
+
</li>
|
|
65
|
+
)}
|
|
66
|
+
|
|
67
|
+
{breadcrumbItems.map((item, index) => {
|
|
68
|
+
const isLast = index === breadcrumbItems.length - 1;
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<li key={item.href} className="flex items-center gap-2">
|
|
72
|
+
{(showHome || index > 0) && (
|
|
73
|
+
<ChevronRight
|
|
74
|
+
className="h-4 w-4 text-muted-foreground"
|
|
75
|
+
aria-hidden="true"
|
|
76
|
+
/>
|
|
77
|
+
)}
|
|
78
|
+
|
|
79
|
+
{isLast ? (
|
|
80
|
+
<span
|
|
81
|
+
className="font-medium text-foreground"
|
|
82
|
+
aria-current="page"
|
|
83
|
+
>
|
|
84
|
+
{item.label}
|
|
85
|
+
</span>
|
|
86
|
+
) : (
|
|
87
|
+
<Link
|
|
88
|
+
href={item.href}
|
|
89
|
+
className="text-muted-foreground hover:text-foreground transition-colors"
|
|
90
|
+
>
|
|
91
|
+
{item.label}
|
|
92
|
+
</Link>
|
|
93
|
+
)}
|
|
94
|
+
</li>
|
|
95
|
+
);
|
|
96
|
+
})}
|
|
97
|
+
</ol>
|
|
98
|
+
</nav>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Generate breadcrumb items from pathname
|
|
104
|
+
*/
|
|
105
|
+
function generateBreadcrumbs(pathname: string): BreadcrumbItem[] {
|
|
106
|
+
const segments = pathname.split("/").filter(Boolean);
|
|
107
|
+
const breadcrumbs: BreadcrumbItem[] = [];
|
|
108
|
+
|
|
109
|
+
let currentPath = "";
|
|
110
|
+
for (const segment of segments) {
|
|
111
|
+
currentPath += `/${segment}`;
|
|
112
|
+
|
|
113
|
+
// Format label: remove hyphens, capitalize words
|
|
114
|
+
const label = segment
|
|
115
|
+
.split("-")
|
|
116
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
117
|
+
.join(" ");
|
|
118
|
+
|
|
119
|
+
breadcrumbs.push({
|
|
120
|
+
label,
|
|
121
|
+
href: currentPath,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return breadcrumbs;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Helper function to create custom breadcrumb items
|
|
130
|
+
*/
|
|
131
|
+
export function createBreadcrumbs(...items: BreadcrumbItem[]): BreadcrumbItem[] {
|
|
132
|
+
return items;
|
|
133
|
+
}
|