fonc: travail en cours sur scripts page Produit
This commit is contained in:
parent
08ad871e0c
commit
e01cd343bc
30 changed files with 1110 additions and 994 deletions
|
|
@ -73,11 +73,7 @@ return new Config()
|
||||||
'multiline_comment_opening_closing' => true,
|
'multiline_comment_opening_closing' => true,
|
||||||
'native_constant_invocation' => true,
|
'native_constant_invocation' => true,
|
||||||
'native_function_casing' => true,
|
'native_function_casing' => true,
|
||||||
'native_function_invocation' => [
|
'native_function_invocation' => ['include' => ['@compiler_optimized'], 'scope' => 'namespaced', 'strict' => true],
|
||||||
'include' => ['@compiler_optimized'],
|
|
||||||
'scope' => 'namespaced',
|
|
||||||
'strict' => true,
|
|
||||||
],
|
|
||||||
'native_type_declaration_casing' => true,
|
'native_type_declaration_casing' => true,
|
||||||
'new_expression_parentheses' => true,
|
'new_expression_parentheses' => true,
|
||||||
'no_alias_functions' => ['sets' => ['@all']],
|
'no_alias_functions' => ['sets' => ['@all']],
|
||||||
|
|
|
||||||
24
bun.lock
24
bun.lock
|
|
@ -8,7 +8,7 @@
|
||||||
"@mobily/ts-belt": "v4.0.0-rc.5",
|
"@mobily/ts-belt": "v4.0.0-rc.5",
|
||||||
"@sentry/browser": "^10.47.0",
|
"@sentry/browser": "^10.47.0",
|
||||||
"a11y-dialog": "^8.1.5",
|
"a11y-dialog": "^8.1.5",
|
||||||
"effect": "^4.0.0-beta.46",
|
"effect": "^4.0.0-beta.48",
|
||||||
"lit-html": "^3.3.2",
|
"lit-html": "^3.3.2",
|
||||||
"purify-ts": "2.1.2",
|
"purify-ts": "2.1.2",
|
||||||
"ts-pattern": "^5.9.0",
|
"ts-pattern": "^5.9.0",
|
||||||
|
|
@ -34,9 +34,9 @@
|
||||||
"eslint-plugin-perfectionist": "^5.8.0",
|
"eslint-plugin-perfectionist": "^5.8.0",
|
||||||
"eslint-plugin-sonarjs": "^4.0.2",
|
"eslint-plugin-sonarjs": "^4.0.2",
|
||||||
"fdir": "^6.5.0",
|
"fdir": "^6.5.0",
|
||||||
"globals": "^17.4.0",
|
"globals": "^17.5.0",
|
||||||
"jiti": "^2.6.1",
|
"jiti": "^2.6.1",
|
||||||
"knip": "^6.3.1",
|
"knip": "^6.4.1",
|
||||||
"lightningcss": "^1.32.0",
|
"lightningcss": "^1.32.0",
|
||||||
"lightningcss-cli": "^1.32.0",
|
"lightningcss-cli": "^1.32.0",
|
||||||
"oxlint": "^1.59.0",
|
"oxlint": "^1.59.0",
|
||||||
|
|
@ -46,7 +46,7 @@
|
||||||
"prettier-plugin-pkg": "^0.22.1",
|
"prettier-plugin-pkg": "^0.22.1",
|
||||||
"prettier-plugin-sh": "^0.18.1",
|
"prettier-plugin-sh": "^0.18.1",
|
||||||
"sass-embedded": "^1.99.0",
|
"sass-embedded": "^1.99.0",
|
||||||
"stylelint": "^17.6.0",
|
"stylelint": "^17.7.0",
|
||||||
"stylelint-config-clean-order": "^8.0.1",
|
"stylelint-config-clean-order": "^8.0.1",
|
||||||
"stylelint-config-sass-guidelines": "^13.0.0",
|
"stylelint-config-sass-guidelines": "^13.0.0",
|
||||||
"stylelint-config-standard-scss": "^17.0.0",
|
"stylelint-config-standard-scss": "^17.0.0",
|
||||||
|
|
@ -796,7 +796,7 @@
|
||||||
|
|
||||||
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
||||||
|
|
||||||
"effect": ["effect@4.0.0-beta.46", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.5.3", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.8", "multipasta": "^0.2.7", "toml": "^3.0.0", "uuid": "^13.0.0", "yaml": "^2.8.2" } }, "sha512-3f6gXvvUMtEueCRY0tU76Vq2Pej1SAwwE+s0Owd5nD53yS5n4RZhUA1rlCGFuSbQFA225pGy8vO72+lpvu7u5A=="],
|
"effect": ["effect@4.0.0-beta.48", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.6.0", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.9", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^13.0.0", "yaml": "^2.8.3" } }, "sha512-MMAM/ZabuNdNmgXiin+BAanQXK7qM8mlt7nfXDoJ/Gn9V8i89JlCq+2N0AiWmqFLXjGLA0u3FjiOjSOYQk5uMw=="],
|
||||||
|
|
||||||
"electron-to-chromium": ["electron-to-chromium@1.5.334", "", {}, "sha512-mgjZAz7Jyx1SRCwEpy9wefDS7GvNPazLthHg8eQMJ76wBdGQQDW33TCrUTvQ4wzpmOrv2zrFoD3oNufMdyMpog=="],
|
"electron-to-chromium": ["electron-to-chromium@1.5.334", "", {}, "sha512-mgjZAz7Jyx1SRCwEpy9wefDS7GvNPazLthHg8eQMJ76wBdGQQDW33TCrUTvQ4wzpmOrv2zrFoD3oNufMdyMpog=="],
|
||||||
|
|
||||||
|
|
@ -930,7 +930,7 @@
|
||||||
|
|
||||||
"global-prefix": ["global-prefix@3.0.0", "", { "dependencies": { "ini": "^1.3.5", "kind-of": "^6.0.2", "which": "^1.3.1" } }, "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg=="],
|
"global-prefix": ["global-prefix@3.0.0", "", { "dependencies": { "ini": "^1.3.5", "kind-of": "^6.0.2", "which": "^1.3.1" } }, "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg=="],
|
||||||
|
|
||||||
"globals": ["globals@17.4.0", "", {}, "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw=="],
|
"globals": ["globals@17.5.0", "", {}, "sha512-qoV+HK2yFl/366t2/Cb3+xxPUo5BuMynomoDmiaZBIdbs+0pYbjfZU+twLhGKp4uCZ/+NbtpVepH5bGCxRyy2g=="],
|
||||||
|
|
||||||
"globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="],
|
"globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="],
|
||||||
|
|
||||||
|
|
@ -1076,7 +1076,7 @@
|
||||||
|
|
||||||
"kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="],
|
"kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="],
|
||||||
|
|
||||||
"knip": ["knip@6.3.1", "", { "dependencies": { "@nodelib/fs.walk": "^1.2.3", "fast-glob": "^3.3.3", "formatly": "^0.3.0", "get-tsconfig": "4.13.7", "jiti": "^2.6.0", "minimist": "^1.2.8", "oxc-parser": "^0.121.0", "oxc-resolver": "^11.19.1", "picocolors": "^1.1.1", "picomatch": "^4.0.1", "smol-toml": "^1.6.1", "strip-json-comments": "5.0.3", "unbash": "^2.2.0", "yaml": "^2.8.2", "zod": "^4.1.11" }, "bin": { "knip": "bin/knip.js", "knip-bun": "bin/knip-bun.js" } }, "sha512-22kLJloVcOVOAudCxlFOC0ICAMme7dKsS7pVTEnrmyKGpswb8ieznvAiSKUeFVDJhb01ect6dkDc1Ha1g1sPpg=="],
|
"knip": ["knip@6.4.1", "", { "dependencies": { "@nodelib/fs.walk": "^1.2.3", "fast-glob": "^3.3.3", "formatly": "^0.3.0", "get-tsconfig": "4.13.7", "jiti": "^2.6.0", "minimist": "^1.2.8", "oxc-parser": "^0.121.0", "oxc-resolver": "^11.19.1", "picocolors": "^1.1.1", "picomatch": "^4.0.1", "smol-toml": "^1.6.1", "strip-json-comments": "5.0.3", "unbash": "^2.2.0", "yaml": "^2.8.2", "zod": "^4.1.11" }, "bin": { "knip": "bin/knip.js", "knip-bun": "bin/knip-bun.js" } }, "sha512-Ry+ywmDFSZvKp/jx7LxMgsZWRTs931alV84e60lh0Stf6kSRYqSIUTkviyyDFRcSO3yY1Kpbi83OirN+4lA2Xw=="],
|
||||||
|
|
||||||
"known-css-properties": ["known-css-properties@0.37.0", "", {}, "sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ=="],
|
"known-css-properties": ["known-css-properties@0.37.0", "", {}, "sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ=="],
|
||||||
|
|
||||||
|
|
@ -1484,7 +1484,7 @@
|
||||||
|
|
||||||
"style-search": ["style-search@0.1.0", "", {}, "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg=="],
|
"style-search": ["style-search@0.1.0", "", {}, "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg=="],
|
||||||
|
|
||||||
"stylelint": ["stylelint@17.6.0", "", { "dependencies": { "@csstools/css-calc": "^3.1.1", "@csstools/css-parser-algorithms": "^4.0.0", "@csstools/css-syntax-patches-for-csstree": "^1.1.1", "@csstools/css-tokenizer": "^4.0.0", "@csstools/media-query-list-parser": "^5.0.0", "@csstools/selector-resolve-nested": "^4.0.0", "@csstools/selector-specificity": "^6.0.0", "colord": "^2.9.3", "cosmiconfig": "^9.0.1", "css-functions-list": "^3.3.3", "css-tree": "^3.2.1", "debug": "^4.4.3", "fast-glob": "^3.3.3", "fastest-levenshtein": "^1.0.16", "file-entry-cache": "^11.1.2", "global-modules": "^2.0.0", "globby": "^16.1.1", "globjoin": "^0.1.4", "html-tags": "^5.1.0", "ignore": "^7.0.5", "import-meta-resolve": "^4.2.0", "is-plain-object": "^5.0.0", "mathml-tag-names": "^4.0.0", "meow": "^14.1.0", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.5.8", "postcss-safe-parser": "^7.0.1", "postcss-selector-parser": "^7.1.1", "postcss-value-parser": "^4.2.0", "string-width": "^8.2.0", "supports-hyperlinks": "^4.4.0", "svg-tags": "^1.0.0", "table": "^6.9.0", "write-file-atomic": "^7.0.1" }, "bin": { "stylelint": "bin/stylelint.mjs" } }, "sha512-tokrsMIVAR9vAQ/q3UVEr7S0dGXCi7zkCezPRnS2kqPUulvUh5Vgfwngrk4EoAoW7wnrThqTdnTFN5Ra7CaxIg=="],
|
"stylelint": ["stylelint@17.7.0", "", { "dependencies": { "@csstools/css-calc": "^3.1.1", "@csstools/css-parser-algorithms": "^4.0.0", "@csstools/css-syntax-patches-for-csstree": "^1.1.2", "@csstools/css-tokenizer": "^4.0.0", "@csstools/media-query-list-parser": "^5.0.0", "@csstools/selector-resolve-nested": "^4.0.0", "@csstools/selector-specificity": "^6.0.0", "colord": "^2.9.3", "cosmiconfig": "^9.0.1", "css-functions-list": "^3.3.3", "css-tree": "^3.2.1", "debug": "^4.4.3", "fast-glob": "^3.3.3", "fastest-levenshtein": "^1.0.16", "file-entry-cache": "^11.1.2", "global-modules": "^2.0.0", "globby": "^16.2.0", "globjoin": "^0.1.4", "html-tags": "^5.1.0", "ignore": "^7.0.5", "import-meta-resolve": "^4.2.0", "is-plain-object": "^5.0.0", "mathml-tag-names": "^4.0.0", "meow": "^14.1.0", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.5.8", "postcss-safe-parser": "^7.0.1", "postcss-selector-parser": "^7.1.1", "postcss-value-parser": "^4.2.0", "string-width": "^8.2.0", "supports-hyperlinks": "^4.4.0", "svg-tags": "^1.0.0", "table": "^6.9.0", "write-file-atomic": "^7.0.1" }, "bin": { "stylelint": "bin/stylelint.mjs" } }, "sha512-n/+4RheCRl+cecGnF+S/Adz59iCRaK9BVznJYB+a7GOksfwNzjiOPnYv17pTO0HgRse9IiqbMtekGNhOb2tVYQ=="],
|
||||||
|
|
||||||
"stylelint-config-clean-order": ["stylelint-config-clean-order@8.0.1", "", { "peerDependencies": { "stylelint": ">=16", "stylelint-order": ">=6" } }, "sha512-zKjp7BiINXRZOG9m0fE/6UKoM6clPekL+LoAiHMCiQU2hgirKL5G0mKc5Z0ygIhQXfb1+DTRDM0mu6Ecdv4q8g=="],
|
"stylelint-config-clean-order": ["stylelint-config-clean-order@8.0.1", "", { "peerDependencies": { "stylelint": ">=16", "stylelint-order": ">=6" } }, "sha512-zKjp7BiINXRZOG9m0fE/6UKoM6clPekL+LoAiHMCiQU2hgirKL5G0mKc5Z0ygIhQXfb1+DTRDM0mu6Ecdv4q8g=="],
|
||||||
|
|
||||||
|
|
@ -1532,7 +1532,7 @@
|
||||||
|
|
||||||
"to-valid-identifier": ["to-valid-identifier@1.0.0", "", { "dependencies": { "@sindresorhus/base62": "^1.0.0", "reserved-identifiers": "^1.0.0" } }, "sha512-41wJyvKep3yT2tyPqX/4blcfybknGB4D+oETKLs7Q76UiPqRpUJK3hr1nxelyYO0PHKVzJwlu0aCeEAsGI6rpw=="],
|
"to-valid-identifier": ["to-valid-identifier@1.0.0", "", { "dependencies": { "@sindresorhus/base62": "^1.0.0", "reserved-identifiers": "^1.0.0" } }, "sha512-41wJyvKep3yT2tyPqX/4blcfybknGB4D+oETKLs7Q76UiPqRpUJK3hr1nxelyYO0PHKVzJwlu0aCeEAsGI6rpw=="],
|
||||||
|
|
||||||
"toml": ["toml@3.0.0", "", {}, "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="],
|
"toml": ["toml@4.1.1", "", {}, "sha512-EBJnVBr3dTXdA89WVFoAIPUqkBjxPMwRqsfuo1r240tKFHXv3zgca4+NJib/h6TyvGF7vOawz0jGuryJCdNHrw=="],
|
||||||
|
|
||||||
"ts-api-utils": ["ts-api-utils@2.5.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="],
|
"ts-api-utils": ["ts-api-utils@2.5.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="],
|
||||||
|
|
||||||
|
|
@ -1632,6 +1632,10 @@
|
||||||
|
|
||||||
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
||||||
|
|
||||||
|
"@gcch/configuration-eslint/globals": ["globals@17.4.0", "", {}, "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw=="],
|
||||||
|
|
||||||
|
"@gcch/configuration-oxlint/globals": ["globals@17.4.0", "", {}, "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw=="],
|
||||||
|
|
||||||
"@keyv/bigmap/keyv": ["keyv@5.6.0", "", { "dependencies": { "@keyv/serialize": "^1.1.1" } }, "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw=="],
|
"@keyv/bigmap/keyv": ["keyv@5.6.0", "", { "dependencies": { "@keyv/serialize": "^1.1.1" } }, "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw=="],
|
||||||
|
|
||||||
"@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
"@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
||||||
|
|
@ -1656,6 +1660,8 @@
|
||||||
|
|
||||||
"eslint-plugin-jsx-a11y/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
|
"eslint-plugin-jsx-a11y/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
|
||||||
|
|
||||||
|
"eslint-plugin-sonarjs/globals": ["globals@17.4.0", "", {}, "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw=="],
|
||||||
|
|
||||||
"eslint-plugin-unicorn/globals": ["globals@16.5.0", "", {}, "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ=="],
|
"eslint-plugin-unicorn/globals": ["globals@16.5.0", "", {}, "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ=="],
|
||||||
|
|
||||||
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||||
|
|
|
||||||
118
composer.lock
generated
118
composer.lock
generated
|
|
@ -3629,15 +3629,15 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "wpackagist-plugin/query-monitor",
|
"name": "wpackagist-plugin/query-monitor",
|
||||||
"version": "4.0.5",
|
"version": "4.0.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "svn",
|
"type": "svn",
|
||||||
"url": "https://plugins.svn.wordpress.org/query-monitor/",
|
"url": "https://plugins.svn.wordpress.org/query-monitor/",
|
||||||
"reference": "tags/4.0.5"
|
"reference": "tags/4.0.6"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://downloads.wordpress.org/plugin/query-monitor.4.0.5.zip"
|
"url": "https://downloads.wordpress.org/plugin/query-monitor.4.0.6.zip"
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"composer/installers": "^1.0 || ^2.0"
|
"composer/installers": "^1.0 || ^2.0"
|
||||||
|
|
@ -4077,6 +4077,75 @@
|
||||||
],
|
],
|
||||||
"time": "2024-05-06T16:37:16+00:00"
|
"time": "2024-05-06T16:37:16+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "ergebnis/agent-detector",
|
||||||
|
"version": "1.1.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/ergebnis/agent-detector.git",
|
||||||
|
"reference": "5b654a9f1ff8a5d2ce6a57568df5ae8801c87f64"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/ergebnis/agent-detector/zipball/5b654a9f1ff8a5d2ce6a57568df5ae8801c87f64",
|
||||||
|
"reference": "5b654a9f1ff8a5d2ce6a57568df5ae8801c87f64",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0 || ~8.6.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"ergebnis/composer-normalize": "^2.50.0",
|
||||||
|
"ergebnis/license": "^2.7.0",
|
||||||
|
"ergebnis/php-cs-fixer-config": "^6.60.2",
|
||||||
|
"ergebnis/phpstan-rules": "^2.13.1",
|
||||||
|
"ergebnis/phpunit-slow-test-detector": "^2.24.0",
|
||||||
|
"ergebnis/rector-rules": "^1.16.0",
|
||||||
|
"fakerphp/faker": "^1.24.1",
|
||||||
|
"infection/infection": "^0.26.6",
|
||||||
|
"phpstan/extension-installer": "^1.4.3",
|
||||||
|
"phpstan/phpstan": "^2.1.46",
|
||||||
|
"phpstan/phpstan-deprecation-rules": "^2.0.4",
|
||||||
|
"phpstan/phpstan-phpunit": "^2.0.16",
|
||||||
|
"phpstan/phpstan-strict-rules": "^2.0.10",
|
||||||
|
"phpunit/phpunit": "^9.6.34",
|
||||||
|
"rector/rector": "^2.4.1"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "1.0-dev"
|
||||||
|
},
|
||||||
|
"composer-normalize": {
|
||||||
|
"indent-size": 2,
|
||||||
|
"indent-style": "space"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Ergebnis\\AgentDetector\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Andreas Möller",
|
||||||
|
"email": "am@localheinz.com",
|
||||||
|
"homepage": "https://localheinz.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Provides a detector for detecting the presence of an agent.",
|
||||||
|
"homepage": "https://github.com/ergebnis/agent-detector",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/ergebnis/agent-detector/issues",
|
||||||
|
"security": "https://github.com/ergebnis/agent-detector/blob/main/.github/SECURITY.md",
|
||||||
|
"source": "https://github.com/ergebnis/agent-detector"
|
||||||
|
},
|
||||||
|
"time": "2026-04-10T13:45:13+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "evenement/evenement",
|
"name": "evenement/evenement",
|
||||||
"version": "v3.0.2",
|
"version": "v3.0.2",
|
||||||
|
|
@ -4187,22 +4256,23 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "friendsofphp/php-cs-fixer",
|
"name": "friendsofphp/php-cs-fixer",
|
||||||
"version": "v3.94.2",
|
"version": "v3.95.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
||||||
"reference": "7787ceff91365ba7d623ec410b8f429cdebb4f63"
|
"reference": "a9727678fbd12997f1d9de8f4a37824ed9df1065"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/7787ceff91365ba7d623ec410b8f429cdebb4f63",
|
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/a9727678fbd12997f1d9de8f4a37824ed9df1065",
|
||||||
"reference": "7787ceff91365ba7d623ec410b8f429cdebb4f63",
|
"reference": "a9727678fbd12997f1d9de8f4a37824ed9df1065",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"clue/ndjson-react": "^1.3",
|
"clue/ndjson-react": "^1.3",
|
||||||
"composer/semver": "^3.4",
|
"composer/semver": "^3.4",
|
||||||
"composer/xdebug-handler": "^3.0.5",
|
"composer/xdebug-handler": "^3.0.5",
|
||||||
|
"ergebnis/agent-detector": "^1.1.1",
|
||||||
"ext-filter": "*",
|
"ext-filter": "*",
|
||||||
"ext-hash": "*",
|
"ext-hash": "*",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
|
|
@ -4227,18 +4297,18 @@
|
||||||
"symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0"
|
"symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"facile-it/paraunit": "^1.3.1 || ^2.7.1",
|
"facile-it/paraunit": "^1.3.1 || ^2.8.0",
|
||||||
"infection/infection": "^0.32.3",
|
"infection/infection": "^0.32.6",
|
||||||
"justinrainbow/json-schema": "^6.6.4",
|
"justinrainbow/json-schema": "^6.8.0",
|
||||||
"keradus/cli-executor": "^2.3",
|
"keradus/cli-executor": "^2.3",
|
||||||
"mikey179/vfsstream": "^1.6.12",
|
"mikey179/vfsstream": "^1.6.12",
|
||||||
"php-coveralls/php-coveralls": "^2.9.1",
|
"php-coveralls/php-coveralls": "^2.9.1",
|
||||||
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.7",
|
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.8",
|
||||||
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.7",
|
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.8",
|
||||||
"phpunit/phpunit": "^9.6.34 || ^10.5.63 || ^11.5.51",
|
"phpunit/phpunit": "^9.6.34 || ^10.5.63 || ^11.5.55",
|
||||||
"symfony/polyfill-php85": "^1.33",
|
"symfony/polyfill-php85": "^1.33",
|
||||||
"symfony/var-dumper": "^5.4.48 || ^6.4.32 || ^7.4.4 || ^8.0.4",
|
"symfony/var-dumper": "^5.4.48 || ^6.4.32 || ^7.4.4 || ^8.0.8",
|
||||||
"symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0.1"
|
"symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0.8"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-dom": "For handling output formats in XML",
|
"ext-dom": "For handling output formats in XML",
|
||||||
|
|
@ -4279,7 +4349,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
|
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
|
||||||
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.94.2"
|
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.95.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
|
@ -4287,7 +4357,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-02-20T16:13:53+00:00"
|
"time": "2026-04-12T17:00:09+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "php-standard-library/phpstan-extension",
|
"name": "php-standard-library/phpstan-extension",
|
||||||
|
|
@ -7411,16 +7481,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "webmozart/assert",
|
"name": "webmozart/assert",
|
||||||
"version": "2.2.0",
|
"version": "2.3.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/webmozarts/assert.git",
|
"url": "https://github.com/webmozarts/assert.git",
|
||||||
"reference": "1b99650e7ffcad232624a260bc7fbdec2ffc407c"
|
"reference": "eb0d790f735ba6cff25c683a85a1da0eadeff9e4"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/webmozarts/assert/zipball/1b99650e7ffcad232624a260bc7fbdec2ffc407c",
|
"url": "https://api.github.com/repos/webmozarts/assert/zipball/eb0d790f735ba6cff25c683a85a1da0eadeff9e4",
|
||||||
"reference": "1b99650e7ffcad232624a260bc7fbdec2ffc407c",
|
"reference": "eb0d790f735ba6cff25c683a85a1da0eadeff9e4",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|
@ -7467,9 +7537,9 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/webmozarts/assert/issues",
|
"issues": "https://github.com/webmozarts/assert/issues",
|
||||||
"source": "https://github.com/webmozarts/assert/tree/2.2.0"
|
"source": "https://github.com/webmozarts/assert/tree/2.3.0"
|
||||||
},
|
},
|
||||||
"time": "2026-04-09T16:54:47+00:00"
|
"time": "2026-04-11T10:33:05+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
|
@ -7484,5 +7554,5 @@
|
||||||
"php": ">=8.5"
|
"php": ">=8.5"
|
||||||
},
|
},
|
||||||
"platform-dev": {},
|
"platform-dev": {},
|
||||||
"plugin-api-version": "2.6.0"
|
"plugin-api-version": "2.9.0"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
"@mobily/ts-belt": "v4.0.0-rc.5",
|
"@mobily/ts-belt": "v4.0.0-rc.5",
|
||||||
"@sentry/browser": "^10.47.0",
|
"@sentry/browser": "^10.47.0",
|
||||||
"a11y-dialog": "^8.1.5",
|
"a11y-dialog": "^8.1.5",
|
||||||
"effect": "^4.0.0-beta.46",
|
"effect": "^4.0.0-beta.48",
|
||||||
"lit-html": "^3.3.2",
|
"lit-html": "^3.3.2",
|
||||||
"purify-ts": "2.1.2",
|
"purify-ts": "2.1.2",
|
||||||
"ts-pattern": "^5.9.0",
|
"ts-pattern": "^5.9.0",
|
||||||
|
|
@ -40,9 +40,9 @@
|
||||||
"eslint-plugin-perfectionist": "^5.8.0",
|
"eslint-plugin-perfectionist": "^5.8.0",
|
||||||
"eslint-plugin-sonarjs": "^4.0.2",
|
"eslint-plugin-sonarjs": "^4.0.2",
|
||||||
"fdir": "^6.5.0",
|
"fdir": "^6.5.0",
|
||||||
"globals": "^17.4.0",
|
"globals": "^17.5.0",
|
||||||
"jiti": "^2.6.1",
|
"jiti": "^2.6.1",
|
||||||
"knip": "^6.3.1",
|
"knip": "^6.4.1",
|
||||||
"lightningcss": "^1.32.0",
|
"lightningcss": "^1.32.0",
|
||||||
"lightningcss-cli": "^1.32.0",
|
"lightningcss-cli": "^1.32.0",
|
||||||
"oxlint": "^1.59.0",
|
"oxlint": "^1.59.0",
|
||||||
|
|
@ -52,7 +52,7 @@
|
||||||
"prettier-plugin-pkg": "^0.22.1",
|
"prettier-plugin-pkg": "^0.22.1",
|
||||||
"prettier-plugin-sh": "^0.18.1",
|
"prettier-plugin-sh": "^0.18.1",
|
||||||
"sass-embedded": "^1.99.0",
|
"sass-embedded": "^1.99.0",
|
||||||
"stylelint": "^17.6.0",
|
"stylelint": "^17.7.0",
|
||||||
"stylelint-config-clean-order": "^8.0.1",
|
"stylelint-config-clean-order": "^8.0.1",
|
||||||
"stylelint-config-sass-guidelines": "^13.0.0",
|
"stylelint-config-sass-guidelines": "^13.0.0",
|
||||||
"stylelint-config-standard-scss": "^17.0.0",
|
"stylelint-config-standard-scss": "^17.0.0",
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,7 @@ $templates = ['404.twig'];
|
||||||
*
|
*
|
||||||
* @throws Exception une exception est levée s'il est impossible d'obtenir la date de modification du fichier à charger
|
* @throws Exception une exception est levée s'il est impossible d'obtenir la date de modification du fichier à charger
|
||||||
*/
|
*/
|
||||||
function load_page_resources(): void
|
function load_page_resources(): void {
|
||||||
{
|
|
||||||
Resource::enqueue_style_file(
|
Resource::enqueue_style_file(
|
||||||
handle: 'haiku-atelier-2024-styles-page-a-propos',
|
handle: 'haiku-atelier-2024-styles-page-a-propos',
|
||||||
path: '/assets/css/pages/page-modele-simple.css',
|
path: '/assets/css/pages/page-modele-simple.css',
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,7 @@ use WC_Session_Handler;
|
||||||
header('Content-Type: application/json; charset=utf-8');
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
|
||||||
// TODO: Appliquer le bon calcul pour les montants vs. percentages
|
// TODO: Appliquer le bon calcul pour les montants vs. percentages
|
||||||
function get_discount_amount(WC_Coupon $coupon)
|
function get_discount_amount(WC_Coupon $coupon) {
|
||||||
{
|
|
||||||
if ($coupon->get_discount_type() === 'fixed_cart') {
|
if ($coupon->get_discount_type() === 'fixed_cart') {
|
||||||
return $coupon->get_amount() * 100;
|
return $coupon->get_amount() * 100;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -31,8 +30,7 @@ function get_discount_amount(WC_Coupon $coupon)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_discount_duration(WC_Coupon $coupon): string
|
function get_discount_duration(WC_Coupon $coupon): string {
|
||||||
{
|
|
||||||
if ($coupon->get_discount_type() === 'fixed_cart') {
|
if ($coupon->get_discount_type() === 'fixed_cart') {
|
||||||
return 'once';
|
return 'once';
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,7 @@ declare(strict_types=1);
|
||||||
use Carbon_Fields\Container;
|
use Carbon_Fields\Container;
|
||||||
use Carbon_Fields\Field;
|
use Carbon_Fields\Field;
|
||||||
|
|
||||||
function cree_champs_personnalises_produit(): void
|
function cree_champs_personnalises_produit(): void {
|
||||||
{
|
|
||||||
Container::make('post_meta', "Product's Details")
|
Container::make('post_meta', "Product's Details")
|
||||||
->where('post_type', '=', 'product')
|
->where('post_type', '=', 'product')
|
||||||
->add_fields([
|
->add_fields([
|
||||||
|
|
@ -27,8 +26,7 @@ function cree_champs_personnalises_produit(): void
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function cree_champ_personnalise_commande($order): void
|
function cree_champ_personnalise_commande($order): void {
|
||||||
{
|
|
||||||
woocommerce_wp_text_input([
|
woocommerce_wp_text_input([
|
||||||
'id' => 'tracking_number',
|
'id' => 'tracking_number',
|
||||||
'label' => 'Tracking Number:',
|
'label' => 'Tracking Number:',
|
||||||
|
|
@ -37,8 +35,7 @@ function cree_champ_personnalise_commande($order): void
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function maj_champ_personnalise_commande($order_id): void
|
function maj_champ_personnalise_commande($order_id): void {
|
||||||
{
|
|
||||||
$order = wc_get_order($order_id);
|
$order = wc_get_order($order_id);
|
||||||
$order->update_meta_data('tracking_number', wc_clean($_POST['tracking_number']));
|
$order->update_meta_data('tracking_number', wc_clean($_POST['tracking_number']));
|
||||||
$order->save();
|
$order->save();
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,7 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
function enregistre_controle_personnalise_tinymce(): void
|
function enregistre_controle_personnalise_tinymce(): void {
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* TinyMCE Custom Control.
|
* TinyMCE Custom Control.
|
||||||
*
|
*
|
||||||
|
|
@ -18,16 +17,14 @@ function enregistre_controle_personnalise_tinymce(): void
|
||||||
*
|
*
|
||||||
* @see https://github.com/maddisondesigns
|
* @see https://github.com/maddisondesigns
|
||||||
*/
|
*/
|
||||||
final class ControlesPersonnalises extends WP_Customize_Control
|
final class ControlesPersonnalises extends WP_Customize_Control {
|
||||||
{
|
|
||||||
/** The type of control being rendered. */
|
/** The type of control being rendered. */
|
||||||
public $type = 'editeur_tinymce';
|
public $type = 'editeur_tinymce';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enqueue our scripts and styles.
|
* Enqueue our scripts and styles.
|
||||||
*/
|
*/
|
||||||
public function enqueue(): void
|
public function enqueue(): void {
|
||||||
{
|
|
||||||
wp_enqueue_script(
|
wp_enqueue_script(
|
||||||
handle: 'controle-personnalise-tinymce',
|
handle: 'controle-personnalise-tinymce',
|
||||||
src: get_template_directory_uri() . '/assets/vendor/controle-personnalise-tinymce.js',
|
src: get_template_directory_uri() . '/assets/vendor/controle-personnalise-tinymce.js',
|
||||||
|
|
@ -41,8 +38,7 @@ function enregistre_controle_personnalise_tinymce(): void
|
||||||
/**
|
/**
|
||||||
* Render the control in the customizer.
|
* Render the control in the customizer.
|
||||||
*/
|
*/
|
||||||
public function render_content(): void
|
public function render_content(): void { ?>
|
||||||
{ ?>
|
|
||||||
<div class="tinymce-control">
|
<div class="tinymce-control">
|
||||||
<span class="customize-control-title"><?php echo esc_html($this->label); ?></span>
|
<span class="customize-control-title"><?php echo esc_html($this->label); ?></span>
|
||||||
<?php if (!empty($this->description)) { ?>
|
<?php if (!empty($this->description)) { ?>
|
||||||
|
|
@ -59,8 +55,7 @@ function enregistre_controle_personnalise_tinymce(): void
|
||||||
/**
|
/**
|
||||||
* Pass our TinyMCE toolbar string to JavaScript.
|
* Pass our TinyMCE toolbar string to JavaScript.
|
||||||
*/
|
*/
|
||||||
public function to_json(): void
|
public function to_json(): void {
|
||||||
{
|
|
||||||
parent::to_json();
|
parent::to_json();
|
||||||
|
|
||||||
$this->json['skyrockettinymcetoolbar1'] = isset($this->input_attrs['toolbar1'])
|
$this->json['skyrockettinymcetoolbar1'] = isset($this->input_attrs['toolbar1'])
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,7 @@ use function is_float;
|
||||||
use function is_int;
|
use function is_int;
|
||||||
use function is_string;
|
use function is_string;
|
||||||
|
|
||||||
final readonly class Cart
|
final readonly class Cart {
|
||||||
{
|
|
||||||
public function __construct() {}
|
public function __construct() {}
|
||||||
|
|
||||||
/** La valeur par défaut d'une donnée invalide du Panier. */
|
/** La valeur par défaut d'une donnée invalide du Panier. */
|
||||||
|
|
@ -23,8 +22,7 @@ final readonly class Cart
|
||||||
*
|
*
|
||||||
* @return array<int,string>
|
* @return array<int,string>
|
||||||
*/
|
*/
|
||||||
public static function get_allowed_countries(): array
|
public static function get_allowed_countries(): array {
|
||||||
{
|
|
||||||
return [
|
return [
|
||||||
'AD',
|
'AD',
|
||||||
'AL',
|
'AL',
|
||||||
|
|
@ -97,8 +95,7 @@ final readonly class Cart
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function parse_cart_value(int|float|string|bool $cart_value): string
|
public static function parse_cart_value(int|float|string|bool $cart_value): string {
|
||||||
{
|
|
||||||
if (is_int($cart_value) || is_float($cart_value)) {
|
if (is_int($cart_value) || is_float($cart_value)) {
|
||||||
return self::format_number($cart_value);
|
return self::format_number($cart_value);
|
||||||
}
|
}
|
||||||
|
|
@ -113,14 +110,14 @@ final readonly class Cart
|
||||||
return '0.00';
|
return '0.00';
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function format_number(int|float $number): string
|
private static function format_number(int|float $number): string {
|
||||||
{
|
|
||||||
$formatted_number = Number::format(
|
$formatted_number = Number::format(
|
||||||
number: $number,
|
number: $number,
|
||||||
// precision et max_precision sont mutuellement exclusifs.
|
// precision et max_precision sont mutuellement exclusifs.
|
||||||
precision: 2,
|
precision: 2,
|
||||||
locale: 'fr',
|
locale: 'fr',
|
||||||
);
|
);
|
||||||
|
|
||||||
return is_bool($formatted_number) ? self::DEFAULT_VALUE : $formatted_number;
|
return is_bool($formatted_number) ? self::DEFAULT_VALUE : $formatted_number;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,7 @@ namespace HaikuAtelier\Data;
|
||||||
|
|
||||||
use WC_Product;
|
use WC_Product;
|
||||||
|
|
||||||
final readonly class ProductVariation
|
final readonly class ProductVariation {
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* @param int $id L'ID de la Variation
|
* @param int $id L'ID de la Variation
|
||||||
* @param string $price Le prix de la Variation
|
* @param string $price Le prix de la Variation
|
||||||
|
|
@ -22,8 +21,7 @@ final readonly class ProductVariation
|
||||||
/**
|
/**
|
||||||
* Créé une nouvelle instance de `ProductVariation` à partir d'un `WC_Product`.
|
* Créé une nouvelle instance de `ProductVariation` à partir d'un `WC_Product`.
|
||||||
*/
|
*/
|
||||||
public static function new(WC_Product $product): self
|
public static function new(WC_Product $product): self {
|
||||||
{
|
|
||||||
$id = $product->get_id();
|
$id = $product->get_id();
|
||||||
$price = $product->get_price();
|
$price = $product->get_price();
|
||||||
/** @var list<ProductVariationAttribute> */
|
/** @var list<ProductVariationAttribute> */
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace HaikuAtelier\Data;
|
namespace HaikuAtelier\Data;
|
||||||
|
|
||||||
final readonly class ProductVariationAttribute
|
final readonly class ProductVariationAttribute {
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* @param string $attribute Le slug de l'Attribut
|
* @param string $attribute Le slug de l'Attribut
|
||||||
* @param string $value Le slug de la valeur de l'Attribut
|
* @param string $value Le slug de la valeur de l'Attribut
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,7 @@ declare(strict_types=1);
|
||||||
namespace HaikuAtelier;
|
namespace HaikuAtelier;
|
||||||
|
|
||||||
// Désactive divers transformations du contenu par WordPress
|
// Désactive divers transformations du contenu par WordPress
|
||||||
function desactive_wpautop(): void
|
function desactive_wpautop(): void {
|
||||||
{
|
|
||||||
remove_filter('the_content', 'wpautop');
|
remove_filter('the_content', 'wpautop');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -21,8 +20,7 @@ function desactive_wpautop(): void
|
||||||
*
|
*
|
||||||
* @return array<string, bool> le même tableau avec des configurations en plus
|
* @return array<string, bool> le même tableau avec des configurations en plus
|
||||||
*/
|
*/
|
||||||
function desactive_transformation_contenu_tinymce(array $configuration): array
|
function desactive_transformation_contenu_tinymce(array $configuration): array {
|
||||||
{
|
|
||||||
// Ne supprime pas les retours à la ligne
|
// Ne supprime pas les retours à la ligne
|
||||||
$configuration['remove_linebreaks'] = false;
|
$configuration['remove_linebreaks'] = false;
|
||||||
// Convertis les caractères de retours à la ligne en <br>
|
// Convertis les caractères de retours à la ligne en <br>
|
||||||
|
|
@ -41,21 +39,18 @@ function desactive_transformation_contenu_tinymce(array $configuration): array
|
||||||
*
|
*
|
||||||
* @return array<string, string> le même tableau avec SVG en plus
|
* @return array<string, string> le même tableau avec SVG en plus
|
||||||
*/
|
*/
|
||||||
function autorise_import_svg_mediatheque(array $file_types): array
|
function autorise_import_svg_mediatheque(array $file_types): array {
|
||||||
{
|
|
||||||
$new_filetypes = [];
|
$new_filetypes = [];
|
||||||
$new_filetypes['svg'] = 'image/svg+xml';
|
$new_filetypes['svg'] = 'image/svg+xml';
|
||||||
|
|
||||||
return [...$file_types, ...$new_filetypes];
|
return [...$file_types, ...$new_filetypes];
|
||||||
}
|
}
|
||||||
|
|
||||||
function retire_motifs_blocs_gutenberg(): void
|
function retire_motifs_blocs_gutenberg(): void {
|
||||||
{
|
|
||||||
remove_theme_support('core-block-patterns');
|
remove_theme_support('core-block-patterns');
|
||||||
}
|
}
|
||||||
|
|
||||||
function retire_styles_core_block(): void
|
function retire_styles_core_block(): void {
|
||||||
{
|
|
||||||
wp_dequeue_style('core-block-supports');
|
wp_dequeue_style('core-block-supports');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,7 @@ use function register_taxonomy;
|
||||||
/**
|
/**
|
||||||
* Enregistre la Taxonomie « Collection ».
|
* Enregistre la Taxonomie « Collection ».
|
||||||
*/
|
*/
|
||||||
function enregistre_taxonomie_collection(): void
|
function enregistre_taxonomie_collection(): void {
|
||||||
{
|
|
||||||
$labels = [
|
$labels = [
|
||||||
'add_new_item' => __('Add New Collection'),
|
'add_new_item' => __('Add New Collection'),
|
||||||
'all_items' => __('All Collections'),
|
'all_items' => __('All Collections'),
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,11 @@ use function is_array;
|
||||||
use function Psl\Option\none;
|
use function Psl\Option\none;
|
||||||
use function Psl\Option\some;
|
use function Psl\Option\some;
|
||||||
|
|
||||||
final readonly class Post
|
final readonly class Post {
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* @return Option\Option<mixed>
|
* @return Option\Option<mixed>
|
||||||
*/
|
*/
|
||||||
public static function get_post_meta(int $post_id, string $key): Option\Option
|
public static function get_post_meta(int $post_id, string $key): Option\Option {
|
||||||
{
|
|
||||||
/** @var false|mixed|string */
|
/** @var false|mixed|string */
|
||||||
$value = get_post_meta($post_id, $key, true);
|
$value = get_post_meta($post_id, $key, true);
|
||||||
|
|
||||||
|
|
@ -34,8 +32,7 @@ final readonly class Post
|
||||||
/**
|
/**
|
||||||
* @return Option\Option<array<mixed>>
|
* @return Option\Option<array<mixed>>
|
||||||
*/
|
*/
|
||||||
public static function get_post_meta_array(int $post_id, string $key): Option\Option
|
public static function get_post_meta_array(int $post_id, string $key): Option\Option {
|
||||||
{
|
|
||||||
/** @var array<mixed>|false */
|
/** @var array<mixed>|false */
|
||||||
$value = get_post_meta($post_id, $key, false);
|
$value = get_post_meta($post_id, $key, false);
|
||||||
|
|
||||||
|
|
@ -49,8 +46,7 @@ final readonly class Post
|
||||||
/**
|
/**
|
||||||
* @return Option\Option<array<mixed>>
|
* @return Option\Option<array<mixed>>
|
||||||
*/
|
*/
|
||||||
public static function get_terms(int $post_id, string $taxonomy_name): Option\Option
|
public static function get_terms(int $post_id, string $taxonomy_name): Option\Option {
|
||||||
{
|
|
||||||
/** @var false|list<WP_Term>|WP_Error */
|
/** @var false|list<WP_Term>|WP_Error */
|
||||||
$terms = get_the_terms($post_id, $taxonomy_name);
|
$terms = get_the_terms($post_id, $taxonomy_name);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { Schema } from "effect";
|
||||||
|
import { ProductAttribute } from "./product.ts";
|
||||||
|
|
||||||
|
class AddProductToCart extends Schema.Class<AddProductToCart>("AddProductToCart")({
|
||||||
|
id: Schema.Int,
|
||||||
|
quantity: Schema.Int.check(Schema.isGreaterThan(0)),
|
||||||
|
variation: Schema.Array(ProductAttribute),
|
||||||
|
}) {}
|
||||||
|
|
||||||
|
export { AddProductToCart };
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
// oxlint-disable no-magic-numbers -- Pas besoin ici.
|
||||||
|
import { Schema } from "effect";
|
||||||
|
|
||||||
|
class ProductAttribute extends Schema.Class<ProductAttribute>("ProductAttribute")({
|
||||||
|
/** L'identifiant _(slug)_ de l'Attribut. */
|
||||||
|
attribute: Schema.String,
|
||||||
|
/** La valeur de l'attribut. */
|
||||||
|
value: Schema.String,
|
||||||
|
}) {}
|
||||||
|
|
||||||
|
class ProductVariation extends Schema.Class<ProductVariation>("ProductVariation")({
|
||||||
|
/** Les Attributs présents pour cette Variation. */
|
||||||
|
attributes: Schema.Array(ProductAttribute),
|
||||||
|
/** L'identifiant numérique unique de la Variation. */
|
||||||
|
id: Schema.Int.check(Schema.isGreaterThan(0)),
|
||||||
|
/** Le prix de la Variation. */
|
||||||
|
price: Schema.NonEmptyString,
|
||||||
|
}) {}
|
||||||
|
|
||||||
|
export { ProductAttribute, ProductVariation };
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { Console, Layer, ManagedRuntime, pipe } from "effect";
|
||||||
|
import ProductPageDOM from "./service-dom.ts";
|
||||||
|
import ProductPageElements from "./service-elements.ts";
|
||||||
|
|
||||||
|
const ProductPageRuntime = ManagedRuntime.make(
|
||||||
|
pipe(
|
||||||
|
ProductPageDOM.layer,
|
||||||
|
Layer.provide(ProductPageElements.layer),
|
||||||
|
Layer.tapError(error => Console.error("ProductPageRuntime", "Impossible de créer le Layer :", error)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
export default ProductPageRuntime;
|
||||||
|
|
@ -6,97 +6,28 @@ import {
|
||||||
Effect,
|
Effect,
|
||||||
HashMap,
|
HashMap,
|
||||||
Layer,
|
Layer,
|
||||||
ManagedRuntime,
|
|
||||||
Option,
|
Option,
|
||||||
pipe,
|
pipe,
|
||||||
|
Ref,
|
||||||
|
Schema,
|
||||||
|
SchemaIssue,
|
||||||
Stream,
|
Stream,
|
||||||
} from "effect";
|
} from "effect";
|
||||||
import type { NonEmptyReadonlyArray } from "effect/Array";
|
|
||||||
import type { NoSuchElementError } from "effect/Cause";
|
import type { NoSuchElementError } from "effect/Cause";
|
||||||
import { getAllSelectorFromDocument, getFirstSelectorFromDocument } from "../scripts-effect/lib/dom.ts";
|
import { AddProductToCart } from "../../scripts-effect/schemas/api.ts";
|
||||||
|
import { ProductAttribute, ProductVariation } from "../../scripts-effect/schemas/product.ts";
|
||||||
import {
|
import {
|
||||||
ATTRIBUT_ARIA_CONTROLS,
|
ATTRIBUT_ARIA_CONTROLS,
|
||||||
ATTRIBUT_ARIA_EXPANDED,
|
ATTRIBUT_ARIA_EXPANDED,
|
||||||
ATTRIBUT_DESACTIVE,
|
ATTRIBUT_DESACTIVE,
|
||||||
ATTRIBUT_HIDDEN,
|
ATTRIBUT_HIDDEN,
|
||||||
DOM_BOUTON_AJOUT_PANIER,
|
} from "../constantes/dom.ts";
|
||||||
DOM_BOUTONS_ACCORDEON,
|
import ProductPageElements from "./service-elements.ts";
|
||||||
DOM_CONTENUS_ACCORDEON,
|
import type { DetailEnsemble } from "./types.d.ts";
|
||||||
DOM_PRIX_PRODUIT,
|
|
||||||
} from "./constantes/dom.ts";
|
|
||||||
import type { WCStoreCartAddItemArgsItems } from "./lib/types/api/cart-add-item.d.ts";
|
|
||||||
|
|
||||||
/** Représente un ensemble bouton-contenu d'une Section dans la description du Produit. */
|
|
||||||
type DetailEnsemble = {
|
|
||||||
button: HTMLButtonElement;
|
|
||||||
content: HTMLDivElement;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ProductPageElements extends Context.Service<
|
|
||||||
ProductPageElements,
|
|
||||||
{
|
|
||||||
AddToCartButton: HTMLButtonElement;
|
|
||||||
Details: HashMap.HashMap<string, DetailEnsemble>;
|
|
||||||
DetailsButtons: NonEmptyReadonlyArray<HTMLButtonElement>;
|
|
||||||
DetailsContents: NonEmptyReadonlyArray<HTMLDivElement>;
|
|
||||||
ProductPrice: HTMLParagraphElement;
|
|
||||||
ProductRawJson: HTMLScriptElement;
|
|
||||||
VariationChoiceForm: HTMLFormElement;
|
|
||||||
VariationSelectors: ReadonlyArray<HTMLSelectElement>;
|
|
||||||
}
|
|
||||||
>()("haikuatelier.fr/Produit/ProductPageElements") {
|
|
||||||
static readonly layer = Layer.effect(
|
|
||||||
ProductPageElements,
|
|
||||||
Effect.gen(function*() {
|
|
||||||
const AddToCartButton = yield* getFirstSelectorFromDocument<HTMLButtonElement>(DOM_BOUTON_AJOUT_PANIER);
|
|
||||||
const DetailsButtons = yield* getAllSelectorFromDocument<HTMLButtonElement>(DOM_BOUTONS_ACCORDEON);
|
|
||||||
const DetailsContents = yield* getAllSelectorFromDocument<HTMLDivElement>(DOM_CONTENUS_ACCORDEON);
|
|
||||||
const ProductPrice = yield* getFirstSelectorFromDocument<HTMLParagraphElement>(DOM_PRIX_PRODUIT);
|
|
||||||
const ProductRawJson = yield* getFirstSelectorFromDocument<HTMLScriptElement>("#product-json");
|
|
||||||
const VariationChoiceForm = yield* getFirstSelectorFromDocument<HTMLFormElement>("#variation-choice");
|
|
||||||
const VariationSelectors = yield* pipe(
|
|
||||||
getAllSelectorFromDocument<HTMLSelectElement>(".selecteur-produit select"),
|
|
||||||
Option.orElseSome(() => FxArray.empty<HTMLSelectElement>()),
|
|
||||||
);
|
|
||||||
|
|
||||||
const Details = yield* pipe(
|
|
||||||
DetailsButtons,
|
|
||||||
FxArray.map(
|
|
||||||
(button: HTMLButtonElement, index: number): Effect.Effect<[string, DetailEnsemble], NoSuchElementError> =>
|
|
||||||
Effect.gen(function*() {
|
|
||||||
const contentId = yield* Option.fromNullishOr(button.getAttribute(ATTRIBUT_ARIA_CONTROLS));
|
|
||||||
const content = yield* FxArray.get(DetailsContents, index);
|
|
||||||
|
|
||||||
return [contentId, { button, content } satisfies DetailEnsemble];
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
Effect.all,
|
|
||||||
Effect.map(HashMap.fromIterable<string, DetailEnsemble>),
|
|
||||||
);
|
|
||||||
|
|
||||||
return ProductPageElements.of({
|
|
||||||
AddToCartButton,
|
|
||||||
Details,
|
|
||||||
DetailsButtons,
|
|
||||||
DetailsContents,
|
|
||||||
ProductPrice,
|
|
||||||
ProductRawJson,
|
|
||||||
VariationChoiceForm,
|
|
||||||
VariationSelectors,
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class ProductPageDOM extends Context.Service<
|
class ProductPageDOM extends Context.Service<
|
||||||
ProductPageDOM,
|
ProductPageDOM,
|
||||||
{
|
{
|
||||||
initPriceUpdatesOnVariationChange: () => Effect.Effect<void>;
|
|
||||||
onVariationChangeHandler: () => Effect.Effect<void>;
|
|
||||||
/**
|
|
||||||
* Récupère les Attributs du Produit depuis les Elements au sein du DOM.
|
|
||||||
*/
|
|
||||||
getProductAttributesFromDOM: () => Effect.Effect<ReadonlyArray<WCStoreCartAddItemArgsItems>>;
|
|
||||||
/**
|
/**
|
||||||
* Initialise l'état initial du Bouton d'ajout au Panier.
|
* Initialise l'état initial du Bouton d'ajout au Panier.
|
||||||
*/
|
*/
|
||||||
|
|
@ -110,26 +41,30 @@ class ProductPageDOM extends Context.Service<
|
||||||
*/
|
*/
|
||||||
initDetailInteractions: () => Effect.Effect<void, NoSuchElementError>;
|
initDetailInteractions: () => Effect.Effect<void, NoSuchElementError>;
|
||||||
/**
|
/**
|
||||||
* Met à jour l'état des Sections de la Description du Produit.
|
* Initialise la mise à jour du Prix affiché en fonction du choix de la Varation de Produit.
|
||||||
*/
|
*/
|
||||||
onDetailButtonClickHandler: (evt: Event) => Effect.Effect<void, NoSuchElementError>;
|
initPriceUpdatesOnVariationChange: () => Effect.Effect<void, NoSuchElementError | string>;
|
||||||
/**
|
|
||||||
* Met à jour l'état du Bouton d'ajout au Panier.
|
|
||||||
*/
|
|
||||||
onFormChangeHandler: (evt: Event) => Effect.Effect<void>;
|
|
||||||
/**
|
/**
|
||||||
* Replie toutes les sections de la description du Produit.
|
* Replie toutes les sections de la description du Produit.
|
||||||
*/
|
*/
|
||||||
toggleAllDetails: () => Effect.Effect<void>;
|
initAddToCartButtonClicks: () => unknown;
|
||||||
|
ProductVariations: ReadonlyArray<ProductVariation>;
|
||||||
|
CurrentVariation: Ref.Ref<Option.Option<ProductVariation>>;
|
||||||
}
|
}
|
||||||
>()("haikuatelier.fr/Produit/ProductPageDOM") {
|
>()("haikuatelier.fr/Produit/ProductPageDOM") {
|
||||||
static readonly layer = Layer.effect(
|
static readonly layer = Layer.effect(
|
||||||
ProductPageDOM,
|
ProductPageDOM,
|
||||||
Effect.gen(function*() {
|
Effect.gen(function*() {
|
||||||
const { AddToCartButton, Details, ProductPrice, DetailsButtons, ProductRawJson, VariationChoiceForm, VariationSelectors } =
|
const {
|
||||||
yield* ProductPageElements;
|
AddToCartButton,
|
||||||
|
Details,
|
||||||
const onFormChangeHandler = Effect.fnUntraced(function*(evt: Event) {
|
DetailsButtons,
|
||||||
|
ProductPrice,
|
||||||
|
ProductRawJson,
|
||||||
|
VariationChoiceForm,
|
||||||
|
VariationSelectors,
|
||||||
|
} = yield* ProductPageElements;
|
||||||
|
const onFormChangeHandler = Effect.fn("onFormChangeHandler")(function*(evt: Event): Effect.fn.Return<void> {
|
||||||
// La cible ne peut qu'être un Formulaire.
|
// La cible ne peut qu'être un Formulaire.
|
||||||
const target: HTMLFormElement = evt.target as HTMLFormElement;
|
const target: HTMLFormElement = evt.target as HTMLFormElement;
|
||||||
const isClickAllowed = target.checkValidity() === false;
|
const isClickAllowed = target.checkValidity() === false;
|
||||||
|
|
@ -152,7 +87,9 @@ class ProductPageDOM extends Context.Service<
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const onDetailButtonClickHandler = Effect.fnUntraced(function*(evt: Event) {
|
const onDetailButtonClickHandler = Effect.fn("onDetailButtonClickHandler")(function*(
|
||||||
|
evt: Event,
|
||||||
|
): Effect.fn.Return<void, NoSuchElementError> {
|
||||||
// Empêche la pollution de l'historique de navigation
|
// Empêche la pollution de l'historique de navigation
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
|
|
||||||
|
|
@ -183,13 +120,67 @@ class ProductPageDOM extends Context.Service<
|
||||||
return yield* Effect.void;
|
return yield* Effect.void;
|
||||||
});
|
});
|
||||||
|
|
||||||
const getProductAttributesFromDOM: () => Effect.Effect<ReadonlyArray<WCStoreCartAddItemArgsItems>> = () =>
|
const ProductVariations: ReadonlyArray<ProductVariation> = yield* pipe(
|
||||||
Effect.sync(() =>
|
JSON.parse(ProductRawJson.textContent)?.variations,
|
||||||
|
json => Schema.decodeUnknownEffect(Schema.Array(ProductVariation))(json, { onExcessProperty: "ignore" }),
|
||||||
|
Effect.mapError(error => SchemaIssue.makeFormatterStandardSchemaV1()(error.issue)),
|
||||||
|
Effect.tapCause(Console.error),
|
||||||
|
);
|
||||||
|
|
||||||
|
const getChosenProductAttributesFromDOM = Effect.fn("getChosenProductAttributesFromDOM")(function*() {
|
||||||
|
return yield* pipe(
|
||||||
FxArray.map(VariationSelectors, (select: HTMLSelectElement) => ({
|
FxArray.map(VariationSelectors, (select: HTMLSelectElement) => ({
|
||||||
attribute: select.id,
|
attribute: select.id,
|
||||||
value: select.value,
|
value: select.value,
|
||||||
}))
|
})),
|
||||||
|
variations => Schema.decodeEffect(Schema.Array(ProductAttribute))(variations),
|
||||||
|
Effect.mapError(error => SchemaIssue.makeFormatterDefault()(error.issue)),
|
||||||
|
Effect.tapCause(Console.error),
|
||||||
);
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const CurrentVariation = yield* Ref.make(Option.none<ProductVariation>());
|
||||||
|
|
||||||
|
const onVariationChangeHandler = Effect.fn("onVariationChangeHandler")(function*(): Effect.fn.Return<
|
||||||
|
void,
|
||||||
|
NoSuchElementError | string
|
||||||
|
> {
|
||||||
|
yield* Console.debug("onVariationChangeHandler");
|
||||||
|
// Ne fais rien si le Formulaire n'est pas valide.
|
||||||
|
if (VariationChoiceForm.checkValidity() === false) {
|
||||||
|
yield* Console.debug("onVariationChangeHandler", "Le formulaire est invalide.");
|
||||||
|
return yield* Effect.void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const equivalence = Schema.toEquivalence(Schema.Array(ProductAttribute));
|
||||||
|
const chosenProductAttributes = yield* getChosenProductAttributesFromDOM();
|
||||||
|
const chosenVariation: ProductVariation = yield* FxArray.findFirst(
|
||||||
|
ProductVariations,
|
||||||
|
(variation: ProductVariation) => equivalence(variation.attributes, chosenProductAttributes),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Met à jour la valeur de la Variation choisie dans le Service.
|
||||||
|
yield* Ref.set(Option.some(chosenVariation))(CurrentVariation);
|
||||||
|
|
||||||
|
const newPrice = chosenVariation.price;
|
||||||
|
ProductPrice.textContent = `${newPrice}€`;
|
||||||
|
|
||||||
|
return yield* Effect.void;
|
||||||
|
}, Effect.tapCause(Console.error));
|
||||||
|
|
||||||
|
const onAddToCartButtonHandler = Effect.fn("onAddToCartButtonHandler")(function*() {
|
||||||
|
const chosenVariation = yield* Ref.getUnsafe(CurrentVariation);
|
||||||
|
const productDetails = yield* Schema.decodeEffect(AddProductToCart)(
|
||||||
|
{
|
||||||
|
id: chosenVariation.id,
|
||||||
|
quantity: 1,
|
||||||
|
variation: chosenVariation.attributes,
|
||||||
|
},
|
||||||
|
{ errors: "all" },
|
||||||
|
);
|
||||||
|
|
||||||
|
console.debug(productDetails);
|
||||||
|
});
|
||||||
|
|
||||||
const initAddToCartButtonInitialState = Effect.fn("initAddToCartButtonInitialState")(function*() {
|
const initAddToCartButtonInitialState = Effect.fn("initAddToCartButtonInitialState")(function*() {
|
||||||
/** Est-ce que le Produit affiché est en stock ? */
|
/** Est-ce que le Produit affiché est en stock ? */
|
||||||
|
|
@ -216,31 +207,23 @@ class ProductPageDOM extends Context.Service<
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const initPriceUpdatesOnVariationChange = Effect.fn("initPriceUpdatesOnVariationChange")(function*(){
|
const initAddToCartButtonClicks = Effect.fn("initAddToCartButtonClicks")(function*() {
|
||||||
|
return yield* pipe(
|
||||||
|
Stream.fromEventListener(AddToCartButton, "click"),
|
||||||
|
Stream.tap(onAddToCartButtonHandler),
|
||||||
|
Stream.runDrain,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const initPriceUpdatesOnVariationChange = Effect.fn("initPriceUpdatesOnVariationChange")(
|
||||||
|
function*(): Effect.fn.Return<void, NoSuchElementError | string> {
|
||||||
return yield* pipe(
|
return yield* pipe(
|
||||||
Stream.fromEventListener(VariationChoiceForm, "change"),
|
Stream.fromEventListener(VariationChoiceForm, "change"),
|
||||||
Stream.tap(onVariationChangeHandler),
|
Stream.tap(onVariationChangeHandler),
|
||||||
Stream.runDrain,
|
Stream.runDrain,
|
||||||
)
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
const onVariationChangeHandler = Effect.fn("onVariationChangeHandler")(function*(){
|
|
||||||
if (VariationChoiceForm.checkValidity() === false) {
|
|
||||||
return yield* Effect.void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const variations = JSON.parse(ProductRawJson.textContent)?.variations as ReadonlyArray<unknown>;
|
|
||||||
const chosenAttributes = yield* getProductAttributesFromDOM();
|
|
||||||
|
|
||||||
const equivalence = FxArray.makeEquivalence<{attribute: string,value: string}>((a,b) => {
|
|
||||||
return a.attribute === b.attribute && a.value === b.value;
|
|
||||||
});
|
|
||||||
const chosenVariation = yield* FxArray.findFirst(variations, variation => equivalence(variation.attributes, chosenAttributes));
|
|
||||||
const newPrice = chosenVariation.price;
|
|
||||||
|
|
||||||
ProductPrice.textContent = `${newPrice}€`;
|
|
||||||
return yield* Effect.void;
|
|
||||||
});
|
|
||||||
|
|
||||||
const initDetailInteractions = Effect.fn("initDetailInteractions")(function*() {
|
const initDetailInteractions = Effect.fn("initDetailInteractions")(function*() {
|
||||||
return yield* pipe(
|
return yield* pipe(
|
||||||
|
|
@ -256,26 +239,16 @@ class ProductPageDOM extends Context.Service<
|
||||||
});
|
});
|
||||||
|
|
||||||
return ProductPageDOM.of({
|
return ProductPageDOM.of({
|
||||||
getProductAttributesFromDOM,
|
CurrentVariation,
|
||||||
|
ProductVariations,
|
||||||
|
initAddToCartButtonClicks,
|
||||||
initAddToCartButtonInitialState,
|
initAddToCartButtonInitialState,
|
||||||
initAddToCartButtonUpdates,
|
initAddToCartButtonUpdates,
|
||||||
initDetailInteractions,
|
initDetailInteractions,
|
||||||
initPriceUpdatesOnVariationChange,
|
initPriceUpdatesOnVariationChange,
|
||||||
onDetailButtonClickHandler,
|
|
||||||
onFormChangeHandler,
|
|
||||||
onVariationChangeHandler,
|
|
||||||
toggleAllDetails,
|
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProductPageRuntime = ManagedRuntime.make(
|
export default ProductPageDOM;
|
||||||
pipe(
|
|
||||||
ProductPageDOM.layer,
|
|
||||||
Layer.provide(ProductPageElements.layer),
|
|
||||||
Layer.tapError(error => Console.error("ManagedRuntime", "Impossible de créer le Layer :", error.name)),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
export { type DetailEnsemble, ProductPageDOM, ProductPageElements, ProductPageRuntime };
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
import { Array as FxArray, Context, Effect, HashMap, Layer, Option, pipe } from "effect";
|
||||||
|
import type { NonEmptyReadonlyArray } from "effect/Array";
|
||||||
|
import type { NoSuchElementError } from "effect/Cause";
|
||||||
|
import { getAllSelectorFromDocument, getFirstSelectorFromDocument } from "../../scripts-effect/lib/dom.ts";
|
||||||
|
import {
|
||||||
|
ATTRIBUT_ARIA_CONTROLS,
|
||||||
|
DOM_BOUTON_AJOUT_PANIER,
|
||||||
|
DOM_BOUTONS_ACCORDEON,
|
||||||
|
DOM_CONTENUS_ACCORDEON,
|
||||||
|
DOM_PRIX_PRODUIT,
|
||||||
|
} from "../constantes/dom.ts";
|
||||||
|
import type { DetailEnsemble } from "./types.d.ts";
|
||||||
|
|
||||||
|
class ProductPageElements extends Context.Service<
|
||||||
|
ProductPageElements,
|
||||||
|
{
|
||||||
|
AddToCartButton: HTMLButtonElement;
|
||||||
|
Details: HashMap.HashMap<string, DetailEnsemble>;
|
||||||
|
DetailsButtons: NonEmptyReadonlyArray<HTMLButtonElement>;
|
||||||
|
DetailsContents: NonEmptyReadonlyArray<HTMLDivElement>;
|
||||||
|
ProductPrice: HTMLParagraphElement;
|
||||||
|
ProductRawJson: HTMLScriptElement;
|
||||||
|
VariationChoiceForm: HTMLFormElement;
|
||||||
|
VariationSelectors: ReadonlyArray<HTMLSelectElement>;
|
||||||
|
}
|
||||||
|
>()("haikuatelier.fr/Produit/ProductPageElements") {
|
||||||
|
static readonly layer = Layer.effect(
|
||||||
|
ProductPageElements,
|
||||||
|
Effect.gen(function*() {
|
||||||
|
const AddToCartButton = yield* getFirstSelectorFromDocument<HTMLButtonElement>(DOM_BOUTON_AJOUT_PANIER);
|
||||||
|
const DetailsButtons = yield* getAllSelectorFromDocument<HTMLButtonElement>(DOM_BOUTONS_ACCORDEON);
|
||||||
|
const DetailsContents = yield* getAllSelectorFromDocument<HTMLDivElement>(DOM_CONTENUS_ACCORDEON);
|
||||||
|
const ProductPrice = yield* getFirstSelectorFromDocument<HTMLParagraphElement>(DOM_PRIX_PRODUIT);
|
||||||
|
const ProductRawJson = yield* getFirstSelectorFromDocument<HTMLScriptElement>("#product-json");
|
||||||
|
const VariationChoiceForm = yield* getFirstSelectorFromDocument<HTMLFormElement>("#variation-choice");
|
||||||
|
const VariationSelectors = yield* pipe(
|
||||||
|
getAllSelectorFromDocument<HTMLSelectElement>(".selecteur-produit select"),
|
||||||
|
Option.orElseSome(() => FxArray.empty<HTMLSelectElement>()),
|
||||||
|
);
|
||||||
|
|
||||||
|
const Details = yield* pipe(
|
||||||
|
DetailsButtons,
|
||||||
|
FxArray.map(
|
||||||
|
(button: HTMLButtonElement, index: number): Effect.Effect<[string, DetailEnsemble], NoSuchElementError> =>
|
||||||
|
Effect.gen(function*() {
|
||||||
|
const contentId = yield* Option.fromNullishOr(button.getAttribute(ATTRIBUT_ARIA_CONTROLS));
|
||||||
|
const content = yield* FxArray.get(DetailsContents, index);
|
||||||
|
|
||||||
|
return [contentId, { button, content } satisfies DetailEnsemble];
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
Effect.all,
|
||||||
|
Effect.map(HashMap.fromIterable<string, DetailEnsemble>),
|
||||||
|
);
|
||||||
|
|
||||||
|
return ProductPageElements.of({
|
||||||
|
AddToCartButton,
|
||||||
|
Details,
|
||||||
|
DetailsButtons,
|
||||||
|
DetailsContents,
|
||||||
|
ProductPrice,
|
||||||
|
ProductRawJson,
|
||||||
|
VariationChoiceForm,
|
||||||
|
VariationSelectors,
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProductPageElements;
|
||||||
6
web/app/themes/haiku-atelier-2024/src/scripts/page-produit/types.d.ts
vendored
Normal file
6
web/app/themes/haiku-atelier-2024/src/scripts/page-produit/types.d.ts
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
/** Représente un ensemble bouton-contenu d'une Section dans la description du Produit. */
|
||||||
|
type DetailEnsemble = {
|
||||||
|
button: HTMLButtonElement;
|
||||||
|
content: HTMLDivElement;
|
||||||
|
};
|
||||||
|
export { DetailEnsemble };
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
// Scripts pour la Page Produit
|
// Scripts pour la Page Produit
|
||||||
|
|
||||||
import { pipe } from "@mobily/ts-belt";
|
import { Console, Effect } from "effect";
|
||||||
import { Console, Effect, pipe as epipe } from "effect";
|
import ProductPageRuntime from "./page-produit/runtime.ts";
|
||||||
|
import ProductPageDOM from "./page-produit/service-dom.ts";
|
||||||
|
|
||||||
import { ProductPageRuntime } from "./scripts-page-produit-service.ts";
|
|
||||||
|
|
||||||
/** États utiles pour les scripts de la page. */
|
/** États utiles pour les scripts de la page. */
|
||||||
type EtatsPage = {
|
type EtatsPage = {
|
||||||
|
|
@ -17,31 +15,6 @@ type EtatsPage = {
|
||||||
// @ts-expect-error -- États injectés par le modèle PHP
|
// @ts-expect-error -- États injectés par le modèle PHP
|
||||||
const ETATS_PAGE: EtatsPage = _etats;
|
const ETATS_PAGE: EtatsPage = _etats;
|
||||||
|
|
||||||
const areArraysEqual = <T>(array1: Array<T>, array2: Array<T>): boolean => {
|
|
||||||
if (array1 !== array2) {
|
|
||||||
const a1 = JSON.stringify(array1.toSorted());
|
|
||||||
const a2 = JSON.stringify(array2.toSorted());
|
|
||||||
return a1 === a2;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updatePriceOnAttributeChange = (): void => {
|
|
||||||
E.VARIATION_CHOICE_FORM.addEventListener("change", (): void => {
|
|
||||||
if (E.VARIATION_CHOICE_FORM.checkValidity() === false) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const productVariations: Array<unknown> = epipe(E.PRODUCT_JSON.textContent, JSON.parse)?.variations;
|
|
||||||
const chosenAttributes = getAttributesFromDom();
|
|
||||||
|
|
||||||
const chosenVariation = productVariations.find(v => areArraysEqual(v.attributes, chosenAttributes));
|
|
||||||
const newPrice: string = chosenVariation.price;
|
|
||||||
|
|
||||||
E.PRIX_PRODUIT.textContent = `${newPrice}€`;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// const ajouteProduitAuPanier = (event: MouseEvent): void => {
|
// const ajouteProduitAuPanier = (event: MouseEvent): void => {
|
||||||
// event.preventDefault();
|
// event.preventDefault();
|
||||||
// console.debug("getAttributeValuesFromDom", getAttributesFromDom());
|
// console.debug("getAttributeValuesFromDom", getAttributesFromDom());
|
||||||
|
|
@ -131,8 +104,24 @@ const updatePriceOnAttributeChange = (): void => {
|
||||||
// };
|
// };
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", (): void => {
|
document.addEventListener("DOMContentLoaded", (): void => {
|
||||||
ProductPageRuntime.runFork(pipe(initAddToCartButton(), Effect.tapCause(Console.error)));
|
console.debug("oups");
|
||||||
ProductPageRuntime.runFork(pipe(initAddToCartInteractionUpdates(), Effect.tapCause(Console.error)));
|
Effect.gen(function*() {
|
||||||
ProductPageRuntime.runFork(pipe(initDetailInteractions(), Effect.tapCause(Console.error)));
|
const DOM = yield* ProductPageDOM;
|
||||||
updatePriceOnAttributeChange();
|
console.debug("oups");
|
||||||
|
|
||||||
|
const effects = Effect.all(
|
||||||
|
[
|
||||||
|
DOM.initAddToCartButtonInitialState(),
|
||||||
|
DOM.initAddToCartButtonUpdates(),
|
||||||
|
DOM.initDetailInteractions(),
|
||||||
|
DOM.initPriceUpdatesOnVariationChange(),
|
||||||
|
DOM.initAddToCartButtonClicks(),
|
||||||
|
],
|
||||||
|
{
|
||||||
|
concurrency: "unbounded",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
yield* effects.pipe(Effect.tapCause(Console.error));
|
||||||
|
}).pipe(ProductPageRuntime.runFork);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -31,10 +31,7 @@ $commande = $order;
|
||||||
$date = new Carbon($commande->get_date_created());
|
$date = new Carbon($commande->get_date_created());
|
||||||
|
|
||||||
$email = [
|
$email = [
|
||||||
'adresses' => [
|
'adresses' => ['facturation' => $commande->get_address('billing'), 'livraison' => $commande->get_address('shipping')],
|
||||||
'facturation' => $commande->get_address('billing'),
|
|
||||||
'livraison' => $commande->get_address('shipping'),
|
|
||||||
],
|
|
||||||
'commande' => ['date' => $date->toDateString(), 'id' => $commande->get_id()],
|
'commande' => ['date' => $date->toDateString(), 'id' => $commande->get_id()],
|
||||||
'livraison' => [
|
'livraison' => [
|
||||||
'methode' => $commande->get_shipping_method(),
|
'methode' => $commande->get_shipping_method(),
|
||||||
|
|
@ -65,9 +62,7 @@ $email = [
|
||||||
];
|
];
|
||||||
}),
|
}),
|
||||||
'totaux' => [
|
'totaux' => [
|
||||||
'sous_total_livraison' => '0' === $commande->get_shipping_total()
|
'sous_total_livraison' => '0' === $commande->get_shipping_total() ? 'Free' : $commande->get_shipping_total() . '€',
|
||||||
? 'Free'
|
|
||||||
: $commande->get_shipping_total() . '€',
|
|
||||||
'sous_total_produits' => $commande->get_subtotal() . '€',
|
'sous_total_produits' => $commande->get_subtotal() . '€',
|
||||||
'sous_total_reduction' => '0.00' === $commande->get_discount_total()
|
'sous_total_reduction' => '0.00' === $commande->get_discount_total()
|
||||||
? '0'
|
? '0'
|
||||||
|
|
|
||||||
|
|
@ -31,10 +31,7 @@ $commande = $order;
|
||||||
$date = new Carbon($commande->get_date_created());
|
$date = new Carbon($commande->get_date_created());
|
||||||
|
|
||||||
$email = [
|
$email = [
|
||||||
'adresses' => [
|
'adresses' => ['facturation' => $commande->get_address('billing'), 'livraison' => $commande->get_address('shipping')],
|
||||||
'facturation' => $commande->get_address('billing'),
|
|
||||||
'livraison' => $commande->get_address('shipping'),
|
|
||||||
],
|
|
||||||
'commande' => ['date' => $date->toDateString(), 'id' => $commande->get_id()],
|
'commande' => ['date' => $date->toDateString(), 'id' => $commande->get_id()],
|
||||||
'paiement' => ['methode' => ''],
|
'paiement' => ['methode' => ''],
|
||||||
'produits' => collect($commande->get_items())->map(static function (WC_Order_Item_Product $article) {
|
'produits' => collect($commande->get_items())->map(static function (WC_Order_Item_Product $article) {
|
||||||
|
|
@ -61,9 +58,7 @@ $email = [
|
||||||
];
|
];
|
||||||
}),
|
}),
|
||||||
'totaux' => [
|
'totaux' => [
|
||||||
'sous_total_livraison' => '0' === $commande->get_shipping_total()
|
'sous_total_livraison' => '0' === $commande->get_shipping_total() ? 'Free' : $commande->get_shipping_total() . '€',
|
||||||
? 'Free'
|
|
||||||
: $commande->get_shipping_total() . '€',
|
|
||||||
'sous_total_produits' => $commande->get_subtotal() . '€',
|
'sous_total_produits' => $commande->get_subtotal() . '€',
|
||||||
'sous_total_reduction' => '0.00' === $commande->get_discount_total()
|
'sous_total_reduction' => '0.00' === $commande->get_discount_total()
|
||||||
? '0'
|
? '0'
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue