@vendure-platform/create 0.1.0 → 0.2.1-nightly.202605190703
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 +37 -27
- package/dist/assets/storefront/.env.example +14 -14
- package/dist/assets/storefront/messages/de.json +2 -3
- package/dist/assets/storefront/messages/en.json +2 -3
- package/dist/assets/storefront/next.config.ts +22 -21
- package/dist/assets/storefront/package.json +75 -75
- package/dist/assets/storefront/public/scenarios/customer/logo.svg +4 -0
- package/dist/assets/storefront/src/app/[locale]/layout.tsx +0 -4
- package/dist/assets/storefront/src/app/[locale]/sign-in/login-form.tsx +70 -102
- package/dist/assets/storefront/src/app/[locale]/sign-in/page.tsx +2 -3
- package/dist/assets/storefront/src/config/scenario-meta.ts +3 -7
- package/dist/assets/storefront/src/config/scenario.ts +14 -30
- package/dist/assets/storefront/src/graphql-env.d.ts +456 -0
- package/dist/assets/storefront/src/scenarios/customer/branding.ts +142 -0
- package/dist/assets/storefront/src/scenarios/customer/hero.tsx +76 -0
- package/dist/assets/storefront/src/scenarios/{default → customer}/index.ts +3 -3
- package/dist/assets/storefront/src/scenarios/{default → customer}/meta.ts +1 -1
- package/dist/assets/storefront/src/schema.graphql +5852 -0
- package/dist/assets/storefront/tsconfig.json +17 -8
- package/dist/assets/templates/README.md.hbs +1 -1
- package/dist/assets/templates/docker-compose.yml.hbs +0 -4
- package/dist/assets/templates/env.hbs +13 -7
- package/dist/assets/templates/environment.d.ts.hbs +1 -5
- package/dist/assets/templates/npmrc.hbs +1 -1
- package/dist/assets/templates/populate.ts.hbs +17 -0
- package/dist/assets/templates/server-package.json.hbs +3 -2
- package/dist/bin/run.js +17 -3
- package/dist/bin/run.js.map +1 -1
- package/dist/cli.d.ts +6 -1
- package/dist/cli.js +147 -25
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +9 -3
- package/dist/index.js.map +1 -1
- package/dist/plugin-registry.d.ts +43 -6
- package/dist/plugin-registry.js +139 -421
- package/dist/plugin-registry.js.map +1 -1
- package/dist/registry.d.ts +18 -0
- package/dist/registry.js +29 -0
- package/dist/registry.js.map +1 -0
- package/dist/scaffold-shared.d.ts +19 -0
- package/dist/scaffold-shared.js +114 -0
- package/dist/scaffold-shared.js.map +1 -0
- package/dist/scaffold-storefront-only.d.ts +6 -0
- package/dist/scaffold-storefront-only.js +101 -0
- package/dist/scaffold-storefront-only.js.map +1 -0
- package/dist/scaffolder.js +22 -42
- package/dist/scaffolder.js.map +1 -1
- package/dist/storefront-copier.d.ts +26 -3
- package/dist/storefront-copier.js +63 -12
- package/dist/storefront-copier.js.map +1 -1
- package/dist/template-renderer.d.ts +24 -7
- package/dist/template-renderer.js +32 -64
- package/dist/template-renderer.js.map +1 -1
- package/dist/types.d.ts +46 -27
- package/package.json +3 -1
- package/dist/assets/storefront/.env.local +0 -1
- package/dist/assets/storefront/public/scenarios/b2b-wholesale/hero/hero-bg.webp +0 -0
- package/dist/assets/storefront/public/scenarios/b2b-wholesale/logo.svg +0 -4
- package/dist/assets/storefront/public/scenarios/default/logo.svg +0 -4
- package/dist/assets/storefront/public/scenarios/kaminpro/hero/hero-bg.webp +0 -0
- package/dist/assets/storefront/public/scenarios/kaminpro/logo.svg +0 -7
- package/dist/assets/storefront/src/components/shared/scenario-paused.tsx +0 -80
- package/dist/assets/storefront/src/scenarios/b2b-wholesale/branding.ts +0 -180
- package/dist/assets/storefront/src/scenarios/b2b-wholesale/hero.tsx +0 -122
- package/dist/assets/storefront/src/scenarios/b2b-wholesale/index.ts +0 -21
- package/dist/assets/storefront/src/scenarios/b2b-wholesale/meta.ts +0 -3
- package/dist/assets/storefront/src/scenarios/default/branding.ts +0 -148
- package/dist/assets/storefront/src/scenarios/default/hero.tsx +0 -107
- package/dist/assets/storefront/src/scenarios/kaminpro/auth-gate.tsx +0 -36
- package/dist/assets/storefront/src/scenarios/kaminpro/branding.ts +0 -238
- package/dist/assets/storefront/src/scenarios/kaminpro/cart-items.tsx +0 -359
- package/dist/assets/storefront/src/scenarios/kaminpro/hero.tsx +0 -123
- package/dist/assets/storefront/src/scenarios/kaminpro/index.ts +0 -50
- package/dist/assets/storefront/src/scenarios/kaminpro/meta.ts +0 -9
- package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/banners.tsx +0 -21
- package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/bom-basket.tsx +0 -221
- package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/btn.tsx +0 -38
- package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/chip.tsx +0 -35
- package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/config-header.tsx +0 -72
- package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/field-row.tsx +0 -126
- package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/info-dot.tsx +0 -38
- package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/login-notice.tsx +0 -81
- package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/module-panel.tsx +0 -144
- package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/quote-dialog.tsx +0 -110
- package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/schematic.tsx +0 -674
- package/dist/assets/storefront/src/scenarios/kaminpro/pdp/components/why-panel.tsx +0 -66
- package/dist/assets/storefront/src/scenarios/kaminpro/pdp/configurator-pdp.tsx +0 -43
- package/dist/assets/storefront/src/scenarios/kaminpro/pdp/configurator-shell.tsx +0 -320
- package/dist/assets/storefront/src/scenarios/kaminpro/pdp/lib/data.ts +0 -150
- package/dist/assets/storefront/src/scenarios/kaminpro/pdp/lib/types.ts +0 -30
- package/dist/assets/storefront/src/scenarios/kaminpro/pdp/styles.css +0 -104
- package/dist/assets/storefront/src/scenarios/kaminpro/shop-by-system.tsx +0 -97
- package/dist/assets/storefront/src/scenarios/kaminpro/system-finder/decision-tree.ts +0 -261
- package/dist/assets/storefront/src/scenarios/kaminpro/system-finder/page.tsx +0 -21
- package/dist/assets/storefront/src/scenarios/kaminpro/system-finder/wizard.tsx +0 -600
- package/dist/assets/storefront/src/schema.graphql.placeholder +0 -5
package/README.md
CHANGED
|
@@ -8,12 +8,12 @@ Scaffold a Vendure Platform project with selected plugins, Docker infrastructure
|
|
|
8
8
|
npx @vendure-platform/create my-project
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
This starts an interactive setup. For non-interactive usage, provide
|
|
11
|
+
This starts an interactive setup. For non-interactive usage, provide both `--plugins` and `--company`:
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
14
|
npx @vendure-platform/create my-project \
|
|
15
15
|
--company "Acme Corp" \
|
|
16
|
-
--plugins
|
|
16
|
+
--plugins approval-workflows,price-rules \
|
|
17
17
|
--no-storefront
|
|
18
18
|
```
|
|
19
19
|
|
|
@@ -21,42 +21,52 @@ npx @vendure-platform/create my-project \
|
|
|
21
21
|
|
|
22
22
|
| Flag | Description | Default |
|
|
23
23
|
|------|-------------|---------|
|
|
24
|
-
| `--plugins <list>` | Comma-separated plugin keys | (interactive prompt) |
|
|
24
|
+
| `--plugins <list>` | Comma-separated optional plugin keys | (interactive prompt) |
|
|
25
25
|
| `--company <name>` | Company name for branding | (derived from project name) |
|
|
26
26
|
| `--no-storefront` | Skip the Next.js storefront | included |
|
|
27
27
|
| `--github` | Create a private GitHub repo via `gh` CLI | no |
|
|
28
|
-
| `--github-org <org>` | GitHub organization for the repo | `vendurehq` |
|
|
28
|
+
| `--github-org <org>` | GitHub organization for the repo (only used with `--github`) | `vendurehq` |
|
|
29
29
|
| `--no-install` | Skip `npm install` after scaffolding | runs install |
|
|
30
30
|
| `--no-git` | Skip `git init` | inits git |
|
|
31
31
|
| `--dry-run` | Print what would be created without writing files | off |
|
|
32
32
|
|
|
33
33
|
When `--plugins` and `--company` are both provided, the CLI runs in non-interactive mode.
|
|
34
34
|
|
|
35
|
-
## Plugin
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
|
44
|
-
|
|
45
|
-
| `
|
|
46
|
-
| `
|
|
47
|
-
| `
|
|
48
|
-
| `
|
|
49
|
-
| `
|
|
50
|
-
| `
|
|
51
|
-
| `
|
|
52
|
-
| `
|
|
53
|
-
| `
|
|
54
|
-
|
|
55
|
-
|
|
35
|
+
## Plugin Tiers
|
|
36
|
+
|
|
37
|
+
Plugins fall into three tiers (mirroring `@vendure-platform/plugin-meta`):
|
|
38
|
+
|
|
39
|
+
- **Core** — always active, can't be disabled. Hidden from the interactive prompt.
|
|
40
|
+
- **Optional** — active by default. Pre-ticked in the prompt; deselect to emit `<key>: false` in the generated `vendure-config.ts`.
|
|
41
|
+
- **Requires config** — inactive by default. Pick from the prompt to enable; the generated config carries the env-var-driven options block.
|
|
42
|
+
|
|
43
|
+
| Key | Plugin | Category | Tier |
|
|
44
|
+
|-----|--------|----------|------|
|
|
45
|
+
| `license-guard` | License Guard | platform | core-requires-config |
|
|
46
|
+
| `org-hierarchy` | Org Hierarchy | b2b | core |
|
|
47
|
+
| `advanced-search` | Advanced Search | search | core |
|
|
48
|
+
| `workflow-engine` | Workflow Engine | platform | core |
|
|
49
|
+
| `approval-workflows` | Approval Workflows | b2b | optional |
|
|
50
|
+
| `global-search` | Global Search | search | optional |
|
|
51
|
+
| `entity-access-control` | Entity Access Control | b2b | optional |
|
|
52
|
+
| `tax-id-management` | Tax ID Management | b2b | optional |
|
|
53
|
+
| `shopping-list` | Shopping List | commerce | optional |
|
|
54
|
+
| `quick-order` | Quick Order | commerce | optional |
|
|
55
|
+
| `reorder-from-history` | Reorder from History | commerce | optional |
|
|
56
|
+
| `store-credit` | Store Credit / Gift Cards | commerce | optional |
|
|
57
|
+
| `quote-management` | Quote Management | b2b | optional |
|
|
58
|
+
| `price-rules` | Price Rules | commerce | optional |
|
|
59
|
+
| `packaging-units` | Packaging Units | commerce | optional |
|
|
60
|
+
| `content-versioning` | Content Versioning | platform | optional |
|
|
61
|
+
| `configurator` | Configurator | commerce | optional |
|
|
62
|
+
| `sso` | SSO | platform | requires-config |
|
|
63
|
+
| `audit-trail` | Audit Trail | platform | requires-config |
|
|
64
|
+
|
|
65
|
+
The canonical list lives in `libs/plugin-meta/src/index.ts`; this table mirrors it.
|
|
56
66
|
|
|
57
67
|
## Dependencies
|
|
58
68
|
|
|
59
|
-
|
|
69
|
+
Inter-plugin dependencies are resolved by `VendurePlatform.init()` at runtime — not by the scaffolder. Selecting `approval-workflows` will activate `org-hierarchy` and `workflow-engine` automatically (they're core anyway). Selecting `global-search` will activate `advanced-search` (also core). Integration sub-plugins between active pairs are wired automatically.
|
|
60
70
|
|
|
61
71
|
## After Scaffolding
|
|
62
72
|
|
|
@@ -67,4 +77,4 @@ npm run populate
|
|
|
67
77
|
npm run dev
|
|
68
78
|
```
|
|
69
79
|
|
|
70
|
-
See the [Quick Start](https://docs.vendure.io/vendure-
|
|
80
|
+
See the [Quick Start](https://docs.vendure.io/vendure-platform/getting-started/quick-start) guide for the full walkthrough.
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
3
|
-
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
|
|
13
|
-
#
|
|
14
|
-
# -
|
|
1
|
+
# Vendure Shop API URL.
|
|
2
|
+
# VENDURE_SHOP_API_URL=https://shop.example.com/shop-api
|
|
3
|
+
|
|
4
|
+
# Public site URL (used for canonical URLs and metadata).
|
|
5
|
+
# NEXT_PUBLIC_SITE_URL=https://www.example.com
|
|
6
|
+
|
|
7
|
+
# Active scenario from src/scenarios/. Defaults to "customer".
|
|
8
|
+
# NEXT_PUBLIC_SCENARIO=customer
|
|
9
|
+
|
|
10
|
+
# Multi-channel: route the storefront to a specific Vendure channel.
|
|
11
|
+
# VENDURE_CHANNEL_TOKEN=your-channel-token
|
|
12
|
+
|
|
13
|
+
# Required: random secret used to authenticate revalidation webhooks.
|
|
14
|
+
# REVALIDATION_SECRET=generate-a-long-random-string
|
|
@@ -408,8 +408,7 @@
|
|
|
408
408
|
"newPassword": "Neues Passwort",
|
|
409
409
|
"confirmPassword": "Passwort bestätigen",
|
|
410
410
|
"resetPassword": "Passwort zurücksetzen",
|
|
411
|
-
"resettingPassword": "Wird zurückgesetzt..."
|
|
412
|
-
"demoAccounts": "Demo-Konten"
|
|
411
|
+
"resettingPassword": "Wird zurückgesetzt..."
|
|
413
412
|
},
|
|
414
413
|
"Search": {
|
|
415
414
|
"title": "Suche",
|
|
@@ -1193,4 +1192,4 @@
|
|
|
1193
1192
|
"max": "Max. {value}",
|
|
1194
1193
|
"range": "{min} – {max}"
|
|
1195
1194
|
}
|
|
1196
|
-
}
|
|
1195
|
+
}
|
|
@@ -408,8 +408,7 @@
|
|
|
408
408
|
"newPassword": "New Password",
|
|
409
409
|
"confirmPassword": "Confirm Password",
|
|
410
410
|
"resetPassword": "Reset password",
|
|
411
|
-
"resettingPassword": "Resetting password..."
|
|
412
|
-
"demoAccounts": "Demo Accounts"
|
|
411
|
+
"resettingPassword": "Resetting password..."
|
|
413
412
|
},
|
|
414
413
|
"Search": {
|
|
415
414
|
"title": "Search",
|
|
@@ -1193,4 +1192,4 @@
|
|
|
1193
1192
|
"max": "Max {value}",
|
|
1194
1193
|
"range": "{min} – {max}"
|
|
1195
1194
|
}
|
|
1196
|
-
}
|
|
1195
|
+
}
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import {NextConfig} from 'next';
|
|
2
|
-
import {config} from 'dotenv';
|
|
3
|
-
import * as path from 'path';
|
|
4
2
|
import createNextIntlPlugin from 'next-intl/plugin';
|
|
5
3
|
|
|
6
|
-
// Load env vars from monorepo root
|
|
7
|
-
config({ path: path.resolve(__dirname, '../.env') });
|
|
8
|
-
|
|
9
4
|
// Derive URLs from port variables if not explicitly set
|
|
10
5
|
const vendurePort = process.env.VENDURE_PORT ?? '3500';
|
|
11
6
|
const storefrontPort = process.env.STOREFRONT_PORT ?? '3001';
|
|
12
7
|
|
|
8
|
+
const activeScenario = process.env.NEXT_PUBLIC_SCENARIO ?? 'default';
|
|
9
|
+
|
|
10
|
+
// Build-time CSS swap: `@/styles/globals` resolves to the active scenario's
|
|
11
|
+
// globals.css. Today only the `vendure-branded` scenario has its own (which
|
|
12
|
+
// imports `@vendure-io/design-tokens`); every other scenario falls back to
|
|
13
|
+
// the shared storefront globals.css.
|
|
14
|
+
const scenarioGlobalsCss = activeScenario === 'vendure-branded'
|
|
15
|
+
? path.resolve(__dirname, 'src/scenarios/vendure-branded/globals.css')
|
|
16
|
+
: path.resolve(__dirname, 'src/app/[locale]/globals.css');
|
|
17
|
+
|
|
13
18
|
const withNextIntl = createNextIntlPlugin('./src/i18n/request.ts');
|
|
14
19
|
|
|
15
20
|
const nextConfig: NextConfig = {
|
|
@@ -44,28 +49,24 @@ const nextConfig: NextConfig = {
|
|
|
44
49
|
VENDURE_SHOP_API_URL: process.env.VENDURE_SHOP_API_URL ?? `http://localhost:${vendurePort}/shop-api`,
|
|
45
50
|
NEXT_PUBLIC_SITE_URL: process.env.NEXT_PUBLIC_SITE_URL ?? `http://localhost:${storefrontPort}`,
|
|
46
51
|
...(process.env.VENDURE_CHANNEL_TOKEN ? { VENDURE_CHANNEL_TOKEN: process.env.VENDURE_CHANNEL_TOKEN } : {}),
|
|
47
|
-
REVALIDATION_SECRET: process.env.REVALIDATION_SECRET
|
|
52
|
+
REVALIDATION_SECRET: process.env.REVALIDATION_SECRET,
|
|
48
53
|
NEXT_PUBLIC_SCENARIO: process.env.NEXT_PUBLIC_SCENARIO ?? 'default',
|
|
49
54
|
},
|
|
55
|
+
webpack: (config) => {
|
|
56
|
+
config.resolve = config.resolve ?? {};
|
|
57
|
+
config.resolve.alias = {
|
|
58
|
+
...(config.resolve.alias ?? {}),
|
|
59
|
+
'@/styles/globals.css': scenarioGlobalsCss,
|
|
60
|
+
};
|
|
61
|
+
return config;
|
|
62
|
+
},
|
|
50
63
|
images: {
|
|
51
64
|
// This is necessary to display images from your local Vendure instance
|
|
52
65
|
dangerouslyAllowLocalIP: true,
|
|
53
66
|
remotePatterns: [
|
|
54
|
-
{
|
|
55
|
-
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
hostname: '**.platform.vendure.io'
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
hostname: 'demo.enterprise.vendure.io'
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
hostname: 'localhost'
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
hostname: '**.code.run'
|
|
68
|
-
}
|
|
67
|
+
{ hostname: 'localhost' },
|
|
68
|
+
// Add hostnames here for any remote Vendure server you fetch images from, e.g.:
|
|
69
|
+
// { hostname: 'shop.example.com' },
|
|
69
70
|
],
|
|
70
71
|
},
|
|
71
72
|
};
|
|
@@ -1,77 +1,77 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
2
|
+
"name": "storefront",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "next dev --webpack --port ${STOREFRONT_PORT:-3001}",
|
|
7
|
+
"build": "next build --webpack",
|
|
8
|
+
"start": "next start",
|
|
9
|
+
"lint": "eslint .",
|
|
10
|
+
"check-types": "tsc --noEmit"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@hookform/resolvers": "^5.2.2",
|
|
14
|
+
"@radix-ui/react-accordion": "^1.2.12",
|
|
15
|
+
"@radix-ui/react-alert-dialog": "^1.1.15",
|
|
16
|
+
"@radix-ui/react-aspect-ratio": "^1.1.8",
|
|
17
|
+
"@radix-ui/react-avatar": "^1.1.11",
|
|
18
|
+
"@radix-ui/react-checkbox": "^1.3.3",
|
|
19
|
+
"@radix-ui/react-collapsible": "^1.1.12",
|
|
20
|
+
"@radix-ui/react-context-menu": "^2.2.16",
|
|
21
|
+
"@radix-ui/react-dialog": "^1.1.15",
|
|
22
|
+
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
23
|
+
"@radix-ui/react-hover-card": "^1.1.15",
|
|
24
|
+
"@radix-ui/react-label": "^2.1.8",
|
|
25
|
+
"@radix-ui/react-menubar": "^1.1.16",
|
|
26
|
+
"@radix-ui/react-navigation-menu": "^1.2.14",
|
|
27
|
+
"@radix-ui/react-popover": "^1.1.15",
|
|
28
|
+
"@radix-ui/react-progress": "^1.1.8",
|
|
29
|
+
"@radix-ui/react-radio-group": "^1.3.8",
|
|
30
|
+
"@radix-ui/react-scroll-area": "^1.2.10",
|
|
31
|
+
"@radix-ui/react-select": "^2.2.6",
|
|
32
|
+
"@radix-ui/react-separator": "^1.1.8",
|
|
33
|
+
"@radix-ui/react-slider": "^1.3.6",
|
|
34
|
+
"@radix-ui/react-slot": "^1.2.4",
|
|
35
|
+
"@radix-ui/react-switch": "^1.2.6",
|
|
36
|
+
"@radix-ui/react-tabs": "^1.1.13",
|
|
37
|
+
"@radix-ui/react-toggle": "^1.1.10",
|
|
38
|
+
"@radix-ui/react-toggle-group": "^1.1.11",
|
|
39
|
+
"@radix-ui/react-tooltip": "^1.2.8",
|
|
40
|
+
"@vendure-io/design-tokens": "^1.1.2",
|
|
41
|
+
"@vendure-platform/storefront-client": "^0.2.0",
|
|
42
|
+
"class-variance-authority": "^0.7.1",
|
|
43
|
+
"clsx": "^2.1.1",
|
|
44
|
+
"cmdk": "^1.1.1",
|
|
45
|
+
"date-fns": "^4.1.0",
|
|
46
|
+
"embla-carousel-react": "^8.6.0",
|
|
47
|
+
"gql.tada": "^1.9.0",
|
|
48
|
+
"input-otp": "^1.4.2",
|
|
49
|
+
"lucide-react": "^0.544.0",
|
|
50
|
+
"next": "^16.0.10",
|
|
51
|
+
"next-intl": "^4.8.3",
|
|
52
|
+
"next-themes": "^0.4.6",
|
|
53
|
+
"react": " ^19.2.0",
|
|
54
|
+
"react-day-picker": "^9.11.3",
|
|
55
|
+
"react-dom": "^19.2.0",
|
|
56
|
+
"react-hook-form": "^7.68.0",
|
|
57
|
+
"react-resizable-panels": "^3.0.6",
|
|
58
|
+
"recharts": "^2.15.4",
|
|
59
|
+
"sonner": "^2.0.7",
|
|
60
|
+
"tailwind-merge": "^3.4.0",
|
|
61
|
+
"vaul": "^1.1.2",
|
|
62
|
+
"zod": "^4.1.13"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@eslint/eslintrc": "^3.3.3",
|
|
66
|
+
"@tailwindcss/postcss": "^4.1.17",
|
|
67
|
+
"@types/node": "^20.19.25",
|
|
68
|
+
"@types/react": "^19.2.7",
|
|
69
|
+
"@types/react-dom": "^19.2.3",
|
|
70
|
+
"baseline-browser-mapping": "^2.9.14",
|
|
71
|
+
"eslint": "^9.39.1",
|
|
72
|
+
"eslint-config-next": "16.0.0",
|
|
73
|
+
"tailwindcss": "^4.1.17",
|
|
74
|
+
"tw-animate-css": "^1.4.0",
|
|
75
|
+
"typescript": "^5.9.3"
|
|
76
|
+
}
|
|
77
77
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 32 32">
|
|
2
|
+
<rect width="32" height="32" rx="7" fill="#0ea5e9"/>
|
|
3
|
+
<path d="M11 10 L17 16 L11 22 M17 10 L21 16 L17 22" stroke="#ffffff" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
4
|
+
</svg>
|
|
@@ -14,7 +14,6 @@ import {CartCountProvider} from "@/lib/cart-count-context";
|
|
|
14
14
|
import {CartCountServer} from "@/components/providers/cart-count-server";
|
|
15
15
|
import {CompanyContextGuard} from "@/components/providers/company-context-guard";
|
|
16
16
|
import {CompanyPermissionsServer} from "@/components/providers/company-permissions-server";
|
|
17
|
-
import {BackendHealthGate} from "@/components/shared/scenario-paused";
|
|
18
17
|
import {getBranding, getBrandingStyleTag} from "@/config/branding";
|
|
19
18
|
// next/root-params provides cache-safe locale resolution. The SWC transform
|
|
20
19
|
// only runs in route files (layout/page), so this import cannot be moved to
|
|
@@ -191,9 +190,6 @@ export default async function LocaleLayout({children, params}: {children: React.
|
|
|
191
190
|
</CompanyPermissionsServer>
|
|
192
191
|
</Suspense>
|
|
193
192
|
</CartCountProvider>
|
|
194
|
-
<Suspense fallback={null}>
|
|
195
|
-
<BackendHealthGate locale={locale} />
|
|
196
|
-
</Suspense>
|
|
197
193
|
</ThemeProvider>
|
|
198
194
|
</NextIntlClientProvider>
|
|
199
195
|
</body>
|
|
@@ -29,19 +29,11 @@ function useLoginSchema() {
|
|
|
29
29
|
|
|
30
30
|
type LoginFormData = z.infer<ReturnType<typeof useLoginSchema>>;
|
|
31
31
|
|
|
32
|
-
const DEFAULT_DEMO_ACCOUNTS = [
|
|
33
|
-
{email: 'buyer@acme-demo.com', label: 'Buyer', description: 'Acme · Places orders (needs approval)'},
|
|
34
|
-
{email: 'approver@acme-demo.com', label: 'Approver', description: 'Acme · Approves/rejects orders'},
|
|
35
|
-
{email: 'admin@acme-demo.com', label: 'Admin', description: 'Acme · Full company management'},
|
|
36
|
-
{email: 'admin@globex-demo.com', label: 'Admin', description: 'Globex · Different company'},
|
|
37
|
-
];
|
|
38
|
-
|
|
39
32
|
interface LoginFormProps {
|
|
40
33
|
redirectTo?: string;
|
|
41
|
-
demoAccounts?: Array<{ email: string; label: string; description: string }>;
|
|
42
34
|
}
|
|
43
35
|
|
|
44
|
-
export function LoginForm({redirectTo
|
|
36
|
+
export function LoginForm({redirectTo}: LoginFormProps) {
|
|
45
37
|
const t = useTranslations('Auth');
|
|
46
38
|
const [isPending, startTransition] = useTransition();
|
|
47
39
|
const [serverError, setServerError] = useState<string | null>(null);
|
|
@@ -77,101 +69,77 @@ export function LoginForm({redirectTo, demoAccounts}: LoginFormProps) {
|
|
|
77
69
|
? `/register?redirectTo=${encodeURIComponent(redirectTo)}`
|
|
78
70
|
: '/register';
|
|
79
71
|
|
|
80
|
-
const fillDemoAccount = (email: string) => {
|
|
81
|
-
form.setValue('username', email);
|
|
82
|
-
form.setValue('password', 'test');
|
|
83
|
-
};
|
|
84
|
-
|
|
85
72
|
return (
|
|
86
|
-
<
|
|
87
|
-
<
|
|
88
|
-
<
|
|
89
|
-
<
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
<
|
|
96
|
-
|
|
97
|
-
<
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
</FormItem>
|
|
107
|
-
)}
|
|
108
|
-
/>
|
|
109
|
-
|
|
110
|
-
<FormField
|
|
111
|
-
control={form.control}
|
|
112
|
-
name="password"
|
|
113
|
-
render={({field}) => (
|
|
114
|
-
<FormItem>
|
|
115
|
-
<div className="flex items-center justify-between">
|
|
116
|
-
<FormLabel>{t('password')}</FormLabel>
|
|
117
|
-
<Link
|
|
118
|
-
href="/forgot-password"
|
|
119
|
-
className="text-muted-foreground hover:text-primary text-sm"
|
|
120
|
-
>
|
|
121
|
-
{t('forgotPassword')}
|
|
122
|
-
</Link>
|
|
123
|
-
</div>
|
|
124
|
-
|
|
125
|
-
<FormControl>
|
|
126
|
-
<Input
|
|
127
|
-
type="password"
|
|
128
|
-
placeholder="••••••••"
|
|
129
|
-
disabled={isPending}
|
|
130
|
-
{...field}
|
|
131
|
-
/>
|
|
132
|
-
</FormControl>
|
|
133
|
-
<FormMessage/>
|
|
134
|
-
</FormItem>
|
|
135
|
-
)}
|
|
136
|
-
/>
|
|
137
|
-
|
|
138
|
-
{serverError && (
|
|
139
|
-
<div className="text-sm text-destructive">
|
|
140
|
-
{serverError}
|
|
141
|
-
</div>
|
|
73
|
+
<Card>
|
|
74
|
+
<Form {...form}>
|
|
75
|
+
<form onSubmit={form.handleSubmit(onSubmit)}>
|
|
76
|
+
<CardContent className="space-y-4">
|
|
77
|
+
<FormField
|
|
78
|
+
control={form.control}
|
|
79
|
+
name="username"
|
|
80
|
+
render={({field}) => (
|
|
81
|
+
<FormItem>
|
|
82
|
+
<FormLabel>{t('email')}</FormLabel>
|
|
83
|
+
<FormControl>
|
|
84
|
+
<Input
|
|
85
|
+
type="email"
|
|
86
|
+
placeholder="you@example.com"
|
|
87
|
+
disabled={isPending}
|
|
88
|
+
{...field}
|
|
89
|
+
/>
|
|
90
|
+
</FormControl>
|
|
91
|
+
<FormMessage/>
|
|
92
|
+
</FormItem>
|
|
142
93
|
)}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
94
|
+
/>
|
|
95
|
+
|
|
96
|
+
<FormField
|
|
97
|
+
control={form.control}
|
|
98
|
+
name="password"
|
|
99
|
+
render={({field}) => (
|
|
100
|
+
<FormItem>
|
|
101
|
+
<div className="flex items-center justify-between">
|
|
102
|
+
<FormLabel>{t('password')}</FormLabel>
|
|
103
|
+
<Link
|
|
104
|
+
href="/forgot-password"
|
|
105
|
+
className="text-muted-foreground hover:text-primary text-sm"
|
|
106
|
+
>
|
|
107
|
+
{t('forgotPassword')}
|
|
108
|
+
</Link>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
<FormControl>
|
|
112
|
+
<Input
|
|
113
|
+
type="password"
|
|
114
|
+
placeholder="••••••••"
|
|
115
|
+
disabled={isPending}
|
|
116
|
+
{...field}
|
|
117
|
+
/>
|
|
118
|
+
</FormControl>
|
|
119
|
+
<FormMessage/>
|
|
120
|
+
</FormItem>
|
|
121
|
+
)}
|
|
122
|
+
/>
|
|
158
123
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
124
|
+
{serverError && (
|
|
125
|
+
<div className="text-sm text-destructive">
|
|
126
|
+
{serverError}
|
|
127
|
+
</div>
|
|
128
|
+
)}
|
|
129
|
+
<Button type="submit" className="w-full" disabled={isPending}>
|
|
130
|
+
{isPending ? t('signingIn') : t('signIn')}
|
|
131
|
+
</Button>
|
|
132
|
+
</CardContent>
|
|
133
|
+
<CardFooter className="flex flex-col space-y-4 mt-2">
|
|
134
|
+
<div className="text-muted-foreground text-sm text-center">
|
|
135
|
+
{t('noAccount')}{' '}
|
|
136
|
+
<Link href={registerHref} className="hover:text-primary underline">
|
|
137
|
+
{t('register')}
|
|
138
|
+
</Link>
|
|
139
|
+
</div>
|
|
140
|
+
</CardFooter>
|
|
141
|
+
</form>
|
|
142
|
+
</Form>
|
|
143
|
+
</Card>
|
|
176
144
|
);
|
|
177
145
|
}
|
|
@@ -6,7 +6,6 @@ import {LoginForm} from "./login-form";
|
|
|
6
6
|
import {Card, CardContent, CardFooter} from "@/components/ui/card";
|
|
7
7
|
import {Skeleton} from "@/components/ui/skeleton";
|
|
8
8
|
import {getActiveCustomer} from "@/lib/vendure/actions";
|
|
9
|
-
import {getBranding} from "@/config/branding";
|
|
10
9
|
import {locale as rootLocale} from 'next/root-params';
|
|
11
10
|
import {type Locale} from '@/i18n/routing';
|
|
12
11
|
import {AuthPageShell} from '@/components/layout/auth-page-shell';
|
|
@@ -56,7 +55,7 @@ async function SignInContent({searchParams, locale}: { searchParams: Promise<Rec
|
|
|
56
55
|
redirect(`/${locale}${safeRedirect}`);
|
|
57
56
|
}
|
|
58
57
|
|
|
59
|
-
return <LoginForm redirectTo={redirectTo}
|
|
58
|
+
return <LoginForm redirectTo={redirectTo} />;
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
export default async function SignInPage({searchParams}: {searchParams: Promise<Record<string, string | string[] | undefined>>}) {
|
|
@@ -78,4 +77,4 @@ export default async function SignInPage({searchParams}: {searchParams: Promise<
|
|
|
78
77
|
</Suspense>
|
|
79
78
|
</AuthPageShell>
|
|
80
79
|
);
|
|
81
|
-
}
|
|
80
|
+
}
|