From 0093b41d053e5924a255e30ad293ff47845c866d Mon Sep 17 00:00:00 2001 From: Michael Riehemann Date: Wed, 7 Feb 2024 15:52:49 +0100 Subject: [PATCH 1/2] Changes for Release 2401.0.0 --- .github/workflows/ci.yml | 6 +- CHANGELOG.md | 26 +- Dockerfile | 2 +- README.md | 4 +- apps/spark/index.html | 2 +- apps/spark/package.json | 72 +- .../spark/public/favicon-apple-touch-icon.png | Bin 0 -> 5956 bytes apps/spark/public/favicon.ico | Bin 15086 -> 15086 bytes apps/spark/public/locales/de/translation.json | 137 + apps/spark/public/locales/en/translation.json | 137 + apps/spark/public/locales/fr/translation.json | 137 + apps/spark/public/locales/it/translation.json | 137 + apps/spark/public/logo192.png | Bin 5347 -> 0 bytes apps/spark/public/logo512.png | Bin 9664 -> 0 bytes apps/spark/public/manifest.json | 10 - apps/spark/src/components/App/App.tsx | 46 +- apps/spark/src/components/App/AppRoutes.tsx | 6 + apps/spark/src/components/App/GlobalStyle.tsx | 82 +- apps/spark/src/components/Button/Button.tsx | 83 +- apps/spark/src/components/CTA/CTA.tsx | 4 +- apps/spark/src/components/Cart/CartList.tsx | 136 + .../src/components/Cart/DetailedCart.tsx | 279 + apps/spark/src/components/Cart/HeaderCart.tsx | 103 + apps/spark/src/components/Cart/SideCart.tsx | 71 + .../src/components/Cart/assets/basket.svg | 20 + .../src/components/Checkout/CheckoutPage.tsx | 56 + .../Checkout/assets/checkout-success.svg | 68 + apps/spark/src/components/Details/Detail.tsx | 5 +- .../src/components/Details/DetailPerson.tsx | 5 +- .../src/components/Details/DetailedMedia.tsx | 2 +- .../views/CMPicture.asPreview.tsx | 4 +- .../src/components/Header/CountryFlagIcon.tsx | 29 + .../spark/src/components/Header/Hamburger.tsx | 2 +- apps/spark/src/components/Header/Header.tsx | 7 +- .../src/components/Header/LanguageChooser.tsx | 112 +- .../src/components/Header/assets/logo.svg | 22 +- .../src/components/HeroBanner/HeroBanner.tsx | 2 +- .../spark/src/components/ImageMap/Hotzone.tsx | 31 +- .../ImageMap/assets/imagemap-icon-hover.svg | 6 - .../ImageMap/assets/imagemap-icon.svg | 6 - .../LeftRightBanner/LeftRightBanner.tsx | 2 +- apps/spark/src/components/Link/Link.tsx | 15 +- apps/spark/src/components/Loading/Loading.tsx | 4 +- apps/spark/src/components/Media/Image.tsx | 40 +- .../src/components/Media/VideoPlayer.tsx | 12 +- .../src/components/Media/assets/loader.svg | 15 + apps/spark/src/components/PageGrid/Col.tsx | 8 + .../components/Product/DetailedProduct.tsx | 10 +- .../src/components/Product/ProductActions.tsx | 115 +- .../src/components/Product/ProductAssets.tsx | 88 +- .../src/components/Product/ProductDetails.tsx | 15 +- .../src/components/Product/QuantityButton.tsx | 67 + .../src/components/Product/ShopNowButton.tsx | 22 +- .../Product/assets/wish-outline.svg | 3 + .../components/Product/assets/wish-solid.svg | 3 + .../src/components/Product/assets/wish.svg | 3 - .../Search/Filters/SearchFilter.tsx | 8 +- .../Search/Filters/StringFilterEntry.tsx | 4 +- .../components/Search/HeaderSearchForm.tsx | 20 +- apps/spark/src/components/Search/Search.tsx | 11 +- .../src/components/Search/SearchFilters.tsx | 12 +- .../src/components/Search/SearchResult.tsx | 31 +- .../src/components/Search/SortFilter.tsx | 7 +- .../ShoppableVideo/ShoppableHeroVideo.tsx | 4 +- .../ShoppableVideo/ShoppableVideoContext.tsx | 47 +- .../ShoppableVideo/ShoppableVideoInfoBox.tsx | 69 + .../ShoppableVideo/ShoppableVideoPlayer.tsx | 11 +- .../ShoppableVideo/ShoppableVideoReducer.ts | 25 +- .../ShoppableVideo/TimelineEntry.tsx | 17 +- apps/spark/src/components/Tags/Taglist.tsx | 6 +- apps/spark/src/context/CartContext.tsx | 156 + apps/spark/src/context/CartReducer.ts | 100 + .../spark/src/context/SiteContextProvider.tsx | 7 + apps/spark/src/i18n.ts | 26 + apps/spark/src/index.tsx | 1 + apps/spark/src/models/Banner/Picture.ts | 1 + apps/spark/src/models/Banner/Tag.ts | 2 + apps/spark/src/models/Detail/Detail.ts | 24 +- apps/spark/src/pages/CartPage.tsx | 9 + .../utils/TeaserVariants/variantsHelper.tsx | 25 + .../utils/Translation/TranslationHelper.ts | 29 + apps/standalone-fragment/package.json | 26 +- .../src/components/StandaloneFragment.tsx | 3 - docs/apps/development.md | 2 +- package.json | 11 +- packages/graphql-layer/.eslintrc.js | 18 +- packages/graphql-layer/bin/download-schema.js | 46 - packages/graphql-layer/package.json | 42 +- .../download-interfaces.ts} | 31 +- .../download-metadata.ts} | 39 +- .../download-possible-types.ts} | 36 +- .../graphql-layer/scripts/download-schema.ts | 37 + packages/graphql-layer/scripts/tsconfig.json | 8 + .../src/__downloaded__/schema.json | 31 - .../src/queries/Detail.query.graphql | 1 + .../src/queries/Site.query.graphql | 1 + .../fragments/CMTaxonomy.fragment.graphql | 1 + .../detail/CMVideoDetail.fragment.graphql | 8 + packages/graphql-layer/tsconfig.json | 11 +- packages/preview-integration/package.json | 18 +- packages/view-dispatcher/package.json | 12 +- pnpm-lock.yaml | 5714 +++++++++-------- servers/mocking/package.json | 12 +- servers/stitching/Dockerfile | 6 +- servers/stitching/package.json | 40 +- 105 files changed, 5676 insertions(+), 3409 deletions(-) create mode 100644 apps/spark/public/favicon-apple-touch-icon.png create mode 100644 apps/spark/public/locales/de/translation.json create mode 100644 apps/spark/public/locales/en/translation.json create mode 100644 apps/spark/public/locales/fr/translation.json create mode 100644 apps/spark/public/locales/it/translation.json delete mode 100644 apps/spark/public/logo192.png delete mode 100644 apps/spark/public/logo512.png create mode 100644 apps/spark/src/components/Cart/CartList.tsx create mode 100644 apps/spark/src/components/Cart/DetailedCart.tsx create mode 100644 apps/spark/src/components/Cart/HeaderCart.tsx create mode 100644 apps/spark/src/components/Cart/SideCart.tsx create mode 100644 apps/spark/src/components/Cart/assets/basket.svg create mode 100644 apps/spark/src/components/Checkout/CheckoutPage.tsx create mode 100644 apps/spark/src/components/Checkout/assets/checkout-success.svg create mode 100644 apps/spark/src/components/Header/CountryFlagIcon.tsx delete mode 100644 apps/spark/src/components/ImageMap/assets/imagemap-icon-hover.svg delete mode 100644 apps/spark/src/components/ImageMap/assets/imagemap-icon.svg create mode 100644 apps/spark/src/components/Media/assets/loader.svg create mode 100644 apps/spark/src/components/Product/QuantityButton.tsx create mode 100644 apps/spark/src/components/Product/assets/wish-outline.svg create mode 100644 apps/spark/src/components/Product/assets/wish-solid.svg delete mode 100644 apps/spark/src/components/Product/assets/wish.svg create mode 100644 apps/spark/src/components/ShoppableVideo/ShoppableVideoInfoBox.tsx create mode 100644 apps/spark/src/context/CartContext.tsx create mode 100644 apps/spark/src/context/CartReducer.ts create mode 100644 apps/spark/src/i18n.ts create mode 100644 apps/spark/src/pages/CartPage.tsx create mode 100644 apps/spark/src/utils/TeaserVariants/variantsHelper.tsx create mode 100644 apps/spark/src/utils/Translation/TranslationHelper.ts delete mode 100644 packages/graphql-layer/bin/download-schema.js rename packages/graphql-layer/{bin/download-interfaces.js => scripts/download-interfaces.ts} (56%) mode change 100644 => 100755 rename packages/graphql-layer/{bin/download-metadata.js => scripts/download-metadata.ts} (53%) mode change 100644 => 100755 rename packages/graphql-layer/{bin/download-possible-types.js => scripts/download-possible-types.ts} (51%) mode change 100644 => 100755 create mode 100644 packages/graphql-layer/scripts/download-schema.ts create mode 100644 packages/graphql-layer/scripts/tsconfig.json create mode 100644 packages/graphql-layer/src/queries/fragments/detail/CMVideoDetail.fragment.graphql diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1b9f215..7ba10d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Use pnpm uses: pnpm/action-setup@v2 @@ -22,9 +22,9 @@ jobs: version: 8 - name: Use Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 cache: 'pnpm' - name: Install dependencies diff --git a/CHANGELOG.md b/CHANGELOG.md index faf327d..9877860 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,32 @@ # Changelog +## v2401.0.0 + +*Released 07.02.2024* + +### Breaking Changes: + +- Updated `schema.json` to CoreMedia Content Cloud v12 - 2401.1 and to the latest CoreMedia Campaign Service changes +- Updated `node.js` to 20 LTS + +### Features: + +- Small Design Refresh + with new logo, white header, and animated image map hotzone icons. + Enhanced shoppable video, and product detail page and other small adjustments. +- Added localization and translations (i18n) +- Added shopping cart and checkout functionality + +### Bugfixes and Changes: + +- Updated minor versions of dependencies +- Fix standalone-fragment render error + +--- + ## v2310.0.0 -*Released 24.10.2023* +*Released 20.10.2023* ### Breaking Changes: diff --git a/Dockerfile b/Dockerfile index 9c60ccd..0830538 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,2 +1,2 @@ -FROM node:18 +FROM node:20 RUN npm install -g pnpm@8 diff --git a/README.md b/README.md index 46a96b0..1897f63 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![CoreMedia Labs Logo](https://documentation.coremedia.com/badges/banner_coremedia_labs_wide.png) -![CoreMedia Content Cloud Version](https://img.shields.io/static/v1?message=2310&label=CoreMedia%20Content%20Cloud&style=for-the-badge&labelColor=666666&color=672779 +![CoreMedia Content Cloud Version](https://img.shields.io/static/v1?message=2401&label=CoreMedia%20Content%20Cloud&style=for-the-badge&labelColor=666666&color=672779 "This badge shows the CoreMedia version this project is compatible with. Please read the versioning section of the project to see what other CoreMedia versions are supported and how to find them." ) @@ -50,7 +50,7 @@ Please refer to the [changelog](CHANGELOG.md) for more details. ## Quickstart -You need at least Node.js 18 (LTS), pnpm 7 and a running instance of the CoreMedia Content Cloud. +You need at least Node.js 20 (LTS), pnpm 8 and a running instance of the CoreMedia Content Cloud. Define your environment variables in `.env` file for the stitching server: [servers/stitching/.env](servers/stitching/.env.example) diff --git a/apps/spark/index.html b/apps/spark/index.html index bb46733..064db67 100644 --- a/apps/spark/index.html +++ b/apps/spark/index.html @@ -5,7 +5,7 @@ - + CoreMedia Spark diff --git a/apps/spark/package.json b/apps/spark/package.json index 3dda5a9..8b263da 100644 --- a/apps/spark/package.json +++ b/apps/spark/package.json @@ -17,62 +17,68 @@ "build-storybook": "storybook build -o dist/storybook" }, "dependencies": { - "@apollo/client": "^3.8.6", + "@apollo/client": "^3.9.3", "@coremedia-labs/graphql-layer": "workspace:^", "@coremedia-labs/preview-integration": "workspace:^", "@coremedia-labs/view-dispatcher": "workspace:^", "@js-joda/core": "^5.6.1", "@js-joda/timezone": "^2.18.2", + "country-flag-icons": "^1.5.9", "crypto-hash": "^2.0.1", "graphql": "^16.8.1", - "loglevel": "^1.8.1", + "i18next": "^23.8.2", + "i18next-browser-languagedetector": "^7.2.0", + "i18next-http-backend": "^2.4.3", + "loglevel": "^1.9.1", "query-string": "^7.1.3", "react": "^17.0.2", "react-dom": "^17.0.2", "react-helmet-async": "^1.3.0", + "react-i18next": "^11.18.6", "react-is": "^18.2.0", - "react-player": "^2.13.0", + "react-player": "^2.14.1", + "react-responsive": "^9.0.2", "react-router-dom": "^5.3.4", - "react-slick": "^0.29.0", + "react-slick": "^0.30.1", "require-from-string": "^2.0.2", "slick-carousel": "^1.8.1", "styled-components": "^5.3.11" }, "devDependencies": { - "@storybook/addon-actions": "^7.5.0", - "@storybook/addon-backgrounds": "^7.5.0", - "@storybook/addon-docs": "^7.5.0", - "@storybook/addon-essentials": "^7.5.0", - "@storybook/addon-links": "^7.5.0", - "@storybook/addon-measure": "^7.5.0", - "@storybook/addon-outline": "^7.5.0", - "@storybook/client-api": "^7.5.0", - "@storybook/client-logger": "^7.5.0", - "@storybook/node-logger": "^7.5.0", - "@storybook/react": "^7.5.0", - "@storybook/react-vite": "^7.5.0", - "@types/node": "^18.18.6", - "@types/react": "^17.0.69", - "@types/react-dom": "^17.0.22", + "@storybook/addon-actions": "^7.6.13", + "@storybook/addon-backgrounds": "^7.6.13", + "@storybook/addon-docs": "^7.6.13", + "@storybook/addon-essentials": "^7.6.13", + "@storybook/addon-links": "^7.6.13", + "@storybook/addon-measure": "^7.6.13", + "@storybook/addon-outline": "^7.6.13", + "@storybook/client-api": "^7.6.13", + "@storybook/client-logger": "^7.6.13", + "@storybook/node-logger": "^7.6.13", + "@storybook/react": "^7.6.13", + "@storybook/react-vite": "^7.6.13", + "@types/node": "^20.11.16", + "@types/react": "^17.0.75", + "@types/react-dom": "^17.0.25", "@types/react-router-dom": "^5.3.3", - "@types/react-slick": "^0.23.11", - "@types/styled-components": "^5.1.29", - "@typescript-eslint/eslint-plugin": "^6.8.0", - "@typescript-eslint/parser": "^6.8.0", - "@vitejs/plugin-react-swc": "^3.4.0", - "dotenv": "^16.3.1", - "eslint": "^8.51.0", - "eslint-config-prettier": "^9.0.0", + "@types/react-slick": "^0.23.13", + "@types/styled-components": "^5.1.34", + "@typescript-eslint/eslint-plugin": "^6.21.0", + "@typescript-eslint/parser": "^6.21.0", + "@vitejs/plugin-react-swc": "^3.6.0", + "dotenv": "^16.4.1", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", "eslint-import-resolver-typescript": "^3.6.1", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-prettier": "^5.0.1", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-react": "^7.33.2", "eslint-plugin-storybook": "^0.6.15", - "prettier": "^3.0.3", - "storybook": "^7.5.0", - "typedoc": "^0.25.2", + "prettier": "^3.2.5", + "storybook": "^7.6.13", + "typedoc": "^0.25.7", "typescript": "~5.2.2", - "vite": "^4.5.0", + "vite": "^4.5.2", "vitest": "^0.34.6" }, "browserslist": { diff --git a/apps/spark/public/favicon-apple-touch-icon.png b/apps/spark/public/favicon-apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..db6fd31b9fef91d17d732c291b1e1a97c78fbae1 GIT binary patch literal 5956 zcmc&&WmMEp)c(QJf}luANJzPKtSl@bAtAylNG~NR%>vRT5(1)tbW1lYxgbchu(Wh6 z-K8{0y!=1DAKuUJnRDl!xpSWToO{oiJ2UswD-C4|vWH{<08pr^C~Ds7>i>iU|91XS z5o39)2(0DQeiDXD;{$79SCSKYqQe%ks(&hrGo$IuErOzm2hVTv==@7grIWNBu5+-LWI z?&+O7DQEgMQQi8(-x1EpjZe9=!|^g_&+~Wh6kX*)gb0cg`pH^|EGbEVMWz6eGnu#a zzm#o?J*xXW%Jta=lKXXh?rC}PpM|g!Cs?8n-`EZYjTV$0e2Vjix%g)rKtNLtCtg!(uwtcNXux%{3Gv!n2y`wqbWT$OQgi)Z| zz^ds5Cdl3B;=uE0q9XVGetT?elO(lO;A_=X2Wx=BV|Ag%UJ7@VOWpBbP$CYQ3bPnENLQ$4CrU|t1L7nqg4~QVa+X$G=+(l$ zC}nubG*wWz!QNQ~TIyD=QlRsvw|pR8uuWgWLO1BqORnqjf5E@JUvKZ$jYxll z5$dprlAS+w(VfyEhZ4-I+m-B3b&Or8t~+x6mqMb{L+6JJC?;sCn(f;QnSqK}!OW;B^`<;x36AJNOx@U{qAv za*IGu9CSc~-u#oB#V|#HBngtmQPpq1V1Mn%*%KtJv3DtPIVo6u9dz&>-#LQ5C$IsAi_`L;oXQ2Uf|0pu9acdYWh1e+c?$p|!Pa5I@Die9P>APNve)MT3XE zUpf4;_%A253?%RY!T?(?Nj#wuTXBpc%A6e>S>KRO} zp(16O%9#Q0R^;%6UIRH+&oV0Fd7W#1633M#tv4hL1wTcKuk-^mz1g80F(xtvA;iiu zm7~&%YkfS~))8gsx5YFHQKtp-bSKJK7pyH8$*tV4-Ge zThF)lm`C+?O*i9e^oc5x``uC;c9F3;{xv0d<&^t zdYO!W2}Ovv8#2C)W`w(yf}3u(-3-H~MM)&1=42t??gIey`6*3g@g8Dd4}uMK9dda3 zhxT8;)RpYH?yJ$A&G=c;XM`!fp^K?o(z+%~xXKqv^B9T9%iXuyS_4WWnauE=ON6Ai z0o;NWz7Rphc!bs&Jj6MpT#pfr{a}_(V`QPeAIFesWSkYfBW5sTbH+Q* z`Y;cnP>F!UwtJ#Rap};}7^t@alzIF+FJDoX`GVeUskVd3yO!nTO`*Q)+m!O^L1Q|N zxf4D2>qd0vfxr+Ah1VSAFXIR6+=FjwKVOzk9~k2=zn9SMb16>>)>emG9p&a0SPr>$ zpfLPDScs8i5PLb~TMp>A4BVOFKB$XUGU<6#J$o1W;(JRbZV6Fip=rIq7HxUuIKI!7 zUeRgJ0gaXN=wY6xWvthTx`(`^fihjsKy>DsLhk6qG|!T?2p|hV!Jj;2#hTHiYkimr zA{1W0vEPjEQ-^0C_%p~*vhQO!nkuv}ehVW7pk+r(TM!sM;= z!uJnpVKKV5#iqkuBIbA0(ERl$pQ{%mbOvUVOV*F;JS=2xM(mGYNx&HDh-;@G`7Sux zD&3ouj~?B-@)o-bSW+PF0rGcI7lU=^3S)(f`{4TrNE-#zC{72cykDOp0s=1U91iBH zv%e=EagcaHS5D%n*(W~)fs;rP>2?YKh113LT){Z{sI^@pnJAF`do0X>N^AAb?4i$* zzY;H1f&$!H#K8o37Q|jBv$QqS(2DjZohm7DBf(~$9DT0lwY-DCqmuOr-5GU#14Lm5R^|l2eSezxXOkd&|f+(#Z~$U-gUt$Jo7#wCVxg@5SJsy6R}58LTWtf_F-i* zVp=xq`48s1Y8>T4*KsZZG<1WsbO{c;{81J*Br8+#L4o3YA>Zifv-(?=I6EYiDo(|M=gujflNPXUp$5=#bEFA9O#Z?Fj3PpFAr z?f)&s%Kk(d?i5W^sOH&416Ayf2+7N&A3s{@R%X9xHgeo&K!c=^tlGMbIjE;6+#bv& z4Ss%OyShS-_+aao|8Yt=HBlT6*2@o6xMTzKh%K@f`sK5etHo}UiJYQEIFk7_<4cN5 zWY|Mhf&fqH<=TluuGJ5EW#Qru7QD8Hbz)>uQwN{j?XyO$Nq_%?lf(Y5g)?{=3e!+t z&07yAo|+nQ$A69^gF@e^M{+7%>n<(5Y?sz*MrGVn^CnV^%p^A=~QB$FWcVavVZ1ZuFNQQY!oZS;<#y1+p0aksfsjXJhB7}1~2 zBf*hMf>5U%W6$pp)+^mCGE$ZsE+u+Zy&<+YWvm5r6iCo0}5Z9}z9r%_%tGR=z@o{eEAH>F+mM^`OnpWF>07 zk_ch$Q@Cbfr%LsP9WuDmzw$-2l{-iCFD$~wfYgyj`Nr- zMga&*vRlvDM63tmNhGkL!gnkbD%YMl@13)&1%X#yno=xBA$mzs+K$c5y}dRAe}1?` zb@vRCf5rCne3)&7N!-rlG;(*bs*Rn@ni##OTu>u|sd~q|o!9?@VG-JuZj`|a_ry;?ydFq+ z2#<)gx~N5Ho(-9E!K8E{J`h39gwJuLJt@Iu2ho)9QXFycVROFQ@#edt+^V<9#Zu#q z_S}xu)MTBtyzPun3NC6?icT5pvjmSO>gvn& z$isX5vSQ3wn~NGw_8r~IGt{3@ax=!BLhGkZaeoL(8@`8xtqf$0z+c*sjbAOF;-4b= zLw%w6y3a72-VnjEo6Se{6NzRQ;SOxj%wQ)HylyjX(bp$dlDQ;U+x)V*tMpY%OyWbQ zeoBbX)0)S!&;*&IvfFo;DA`;6+G(({SbLLy%;6H(OgX-ufJ$%c7;((Zr?A+BJ?-^! z4JF6gd_%Ym>hU(X{RJZ2vLl3Isf|cFXX6ujg0?9`7r%((Uwki-)LbTeo)#VAqwL4P zx6v8;!=t8AevLN9kfWgUoT7-lpnI3C`6_VMKVc_N9Ylg{9UCJ#OyyJLq;88#D=(Z2R;bu% zYcJW>iuhQ`6vZQ<%a1}xCwYFcTbc{*nN#jDHp)}DekZfu+Zi?CAPnQZ6qk-+@O>YK zw0fwqnu?i9c^#V?2cEtdzNeta7i>@}K?_T?)A@PO-iv9L3X`4+R(2hKe7lX`v zi{etU4%;Aow=j>3c9K=Os*K=Yc?MfYpJ+a|AcjWP_n6rzolx_qY~7rvq9#twLTUwR zZ(RTjh$cORB==2tNe@nGfWgvRjK=?R7vuVCEUr4hmbMYodLfNt9LK}1Ft~`P2d2et zszML?!u)P78)j*^{Lt}1Mk@et8V~M#zTCZ7dRzS!gRBwS(#=<|P89?@JeY<#Lyl-> zn0=Zg-8RO)Tm)R;+e|7hcpJB2qGm}~9>5qAwda~O5PGr<+umkTE(XKj860?W3LXpz zE$Mf0RBGSt+Bf~!t7ku8jI;^_ZI$=B8W~YCY-VGNX zC(=yjkS-b*9r^2D!(HBKQEJ*kPak^EtG2gw@IWeI0y@#>%vWqSTbp5HBM1dpQOnQv zWiQFBf4Iy1cuTZWszELT)fGj_ec3)B%uuI;CiK4rl`rK3TkoDQ>LDz%1~KKL653OPvL{yxEZG(ym)uO;wz0)5llaYq&5)Z zGw5Q~Bol1NPfRNZS0+zGsqJv}2u(lJp2n_hIuuu;oF^|gentr$_j2)D*jwGhTC?Gl zu4L&4^izBAfMh}V3GC>R?V#xi`5_%TUL3}S)5IE?B5J}?X{a8SoF{ABW3U%Y7+%%{ zJm&4#V(!QMv6>Cby+wt-Pl``&f7laG#GnRUv*HZPG*>eTZ*GP~8nxNpe**zTnE?R{ zpC-b5@&TPT>JqD@$*<=3f&c zPXHry`Kla=R&M-pi5G#3EN_^xk^?q+nsVYI=6#{hOOg2sOTkV)k8n9@sNw0ikoe$Z zbjki)TR-_4FVtRSzD!y8{3&0h3W31&P!W9aMCPZij02sl{S#t9Lcq58x@w=jAgOAl zvIaje=8>2lANuf@35GmUeCng3E!<Q@?S3=fZLupt1Bb^Cfx&DBz++8>8D!y z+Kltdw{0b`E+?Dp{$7ub(Tu%j<&&vaN<(ZAfy|#PyE)yu74de(7{hIXr2YA*DJsLS zr3=|wKHe8BIPOgLov^Z10I2OXI?PFB2Co5uP*E;Lf&?i%Qy%>oA0DgrQ5>#W`R>=_ z_B|vJIP`!_rdmBo)_es7KKCDpihWVu(vUd5E|{_vu(P}AcNRGNyzdLyR}jENCmwpe z1}PV|;GajGKeCe(ec@Ea*Z2W1PiA}9FE{?%qj_bj4#F_ti$h=Vp z(}~s@6Vbqrw46LT@nRWqNcWTVQkRJ_!WGqP03uo%5;vjw(|mTyX*Q3Sse@$^I_}#D z_I6}EH!+}MlDT^`#ke^>u*3Pll4wN`jbEiuxyml++40HB*?n)wq{g$tL2<_>PbBY6 zE)$TI#?0h-Fn1QsvHnY*itf-n{p<=~SXAI=*wS6;CwcWeul}`kme)L<&p;I2ri>P@ zY%2Qxpb%-x9I5Rze8hn1b2VRIv4bNGbX9;z zKYd(FXJQkBD19bg1xBgU42m| ztgY>y(U!697YRefnBQ`Dfgvr;%Q=qV!F`?P^grbWze&@6VX$vR)nA%Ei-P}gN~f-O zy=St|o}Rd##D%nofrsV@?tT7s7{W5B#}9oQ1n#aEC@N|8LD{L7&E>~vfS~{Ywrx0` z*--nZnd!b1W&2|VLr_l6Ay9a5bB({hrX+PF#3eGfg85#svQn^%(w!Lz(@1`8Q4G=z zy|;GeYq;)R;k34GKN_9Zee{hZGU4mUKS^^Z7S%@^4@o@^J><($@N{V8U|@mb6aTuY zDpX7f_<$jq*IW`C^L&tJWO(n4*d*`02aomltf1R=1MI0`6>07CB0_t6Zg$7Ou$yS- znB>E~-zL#~dfm2gKEEvRd83m^SmT)U{c8FBII!|U@0p^DSxb{+sNEd7S@|!`jM#o; zHb$6CM{ITH)!Lt_H`|+i!^X$<2zc)*1tO*e$(C4|HH|JFNB_`B+qRyiL6=_>a(DCS z{jSN58WHF5qe*DqON8HjB26mIwaGy9t&LJET}_DmzQj2954nP&4LVvPrpV$D=xyE7 z*FWx16hJ_`KDd{1ukI*BZ%x%BA^9gT4Zqp6*sgZn?)SfG@oHPrmTZdA{)W2Yun%zxcw{5Bb6` z{mmD?=Mi7{{3>7g&_{jY4ttWeY;(`>N6PN>M?!b`BU69xkGwg{AKq|}Kb!=E0fU+A z3mY&PFql7cfx&>m{FMs~=3#I_e{6v-yci4@F7k!<&$d=u-k%EH)BTbDzw<{H-rx|<6O1`K9S8ixC!RWZ!xvtob;g28~nK!3wRUw9=LZdmNAKCmt6O`q#Ff8>ZM z{>Z#({>Y}=p%)AW3Y!9agqWR8NLhcwoR_1Osy9VnB{;KC}{pfd@OGziO$k`p2!I zTi(4f5ZPy9AachofymZd0}%rTQz!<}1(7A;gXn_tL3Ba+AiAJ@Ko>-ogbxND7%+Ue zv`_U(EyZwsAky=OK;)sD0+B{|V8CDm19IeIKo?v-h%SgM2_LXYM);umtQbTWM3z*a zMV1_Wwq;2$pbP03{s)G$ip6kEAlhR>AW{W}6g)6sFoFR&axtI_wk!z-(FKtu)n~;Z z`m7k{I($%lRt#x2$<_tMfG!9h>Y)FkV(1?ih<3g@5S@E%Aesb&0fT8dh9-S(A%=}$ z7`xQBy0jSjuL?x386Swo!C=5(u1mv!F1UP{#AlHu;e+V2@L} zS4TmAQM8W`&-$tJY;A}KbiYf3 z(f7b$z+eQ!6VJx&N29YDhAo{Erut}@n!^xR*eb?Vd1f!iU4o05=g8_pn5JL>R+V8uj z)oZ=s!Ke=mUxUFYhEaT0K8P-eEU7*tOIzT>1zvM~ANMW@My~>c0fP|?zu^)-2!=6S zB1@{z4u%KOg|hF1*331}4My9YAB-*lgDDWhS6~Qb&hveJKQ9>V_N!p@127oHa1o!C z526do2gj~1f_^gA{D0V_4*2M9*w(%9Z>_Q~*;YF@7(48|U~C;2j9|EsOZXrdL>EMs zRG+b{No47gY;);->{2^?!ztL+#bEddAN>ZtVGr;*7i>PL zJ}U;tt|pMB5&7mP@97AJ(eU6sFsw%x*1(5Hut`73_inMjpBajE=UM>Cl8 zx?ROLRDq!&`Gp7F!Egk+P!5JY5^tOyinTi<6k7-e<6?kz;lnNrP5SKkhIL@b>jR42 z$JRU#hVfu9$dZdebU`tA*wqKXP*4of8oCO7cR(l>1VgQ25M2;iQhoNYt99tZ&_d_m z)6bn2iggCV3t%usV5kPev3r`fLgzm<6dMJOgkTU|5Lr^2qVS`K6J0tb6uS}(jeqy{^3w;>t*zA- z4-9eWe+?gfDzQ?F@|}}Iv6I2@HM-zpD8jC$$EykQhHcQli8??Xc~6`iI+aleaBGu_ z!HHMD0>cP$x1uprhGHdPxCsmmf}u#8RA>(E)-sSI7XxzS)>q*}Ef_9p2?prji)%g@ zQeGGejP=|cI!`SlSBIYkz>qA~t~&9mn?q;R0o>YT0rk}{!O&t~4+gPGv%#>#(#XUTn> z{L`&v6j)#V7@IVpm_7G;77QJse>8IRnJ0$b>}o-^j9fM1dSdR!u}N*3FMy#B7#4tG zi^fSBbLWXy)9tEToAju!rqG2|;@j{IKk(Yi*4~5uPSAfQcJ)axY|=O>PrRDXt|sse ztI>tY__m7H(pbp*VCV$>Ct#EA2E&KMNt?lt(pb+U=FY^>fPelR|MnDhz0vsRgYj)e z`>R4|&Gig?D1rX{kfQ<6KN;WfH2S=XTE+%qj0S3ADRSr}x!X2u(puuAH__+$=<_K2 z!qH&plxu#k-;7CFQ;lUAQ)hLx$7xonj47U$F~L~LSjSk-Si?wEW|leQG)B2Eqddo8 zO|>jupCVsU%(k2{!R*E!%k434RXXF;W@8Al zEw_Kqm@f`mxxZ_yw7(~;a%XI!Q|VS5ykg^WaZclVdD=eI@Ll#r_eu9n_mLOvePsii z_PJ@_rBADZt3Q|9r$sMUYyUVa?aEo{X`GYZ#Tn!4oX@T0Ty7g@iw&HOZsTlpExj7A zbGAE^9)SV$IpmDB3#ErM+kNR@7|pr)tDHC2ao(KLvt~V`boJa{*7I|8`?{zJsa9{qP-fdzlnaCDUbK5 z&TIFHle!YC-j8o?AhxjkNvLbvG-ywf_Q7Zm46?G(Fxh;K< zGe2YBJL8|`Ktn>}WoU5wa@v4~RqR8~Gg0!Varnr%#O+#R*7`DWuH6@;y;<5@COsUo z58BJ5Jpeqa2}w;Ho(9!MT*=TA=lw+x+-7SuNX!{^PC z7#4qLpG#|R0P<+}HXx7hLIYi~ZU0A&WncX63W=jN50GxBbdZGg5y( z4*$Oi8ti<;gN6mHzsLG$i9v=-45H@{n$rLmtY|%ln`q>FA}L{XGB;Mc3hp$7X0e=|RIP zWOBEj9oGLT^7vJTZCKAf9F<9HzVF0@Gc?E3Gg8SR?vZEwoIIn>uEnyp2MrHHL)O>< z8k*VReCuWYPL9wM8a~ooO>-PQBSbGZAP=WxzSoxD$+u=hgI!nGTroo@-hzf7wdI=W zbCG-ZgNBWHXm}YKj!u8Ctv*wOks8KAXs~PBn)iF?Wf(g>9$#?~dfDup9-rNg*yTX< z@;u^(Nyy|x?9&+?|Blnq%P2K zKQttp(cqz%#nQm~|G`)MBA?7aLw9I+kXlNk(2zqf?V3Y|zjS-iwCB4J(CzsNizz6j{9-4>^C6e35qKp#gHxIpiFll5cD$?`$OJ{Dyq< zMe?kXOMGFOdbdAhunRhPEpb{6xpYeMX!*Ybl0QrCEO|4vgPr87&yX(%(kDQkJ7L#m z;^*s$Gwgg=@^P;@B9*j(VB6$(=EHO_KoAv}TXNbM%!d`R$$Ntnq`m+}&l5;i7^Rd?> zvDZn-uberaXO4pFBE+Th#NI)N^t|q1jzPLN&~YSKPGe8^)_dvW*}+&Da{8>qw$LGS ztifkc>9Q>Lvo}0>AD%SO$2cziJ^hT%l`+S&5)VjR$Q*01d56gF*!csPVux%6c zoy?Ir=7}$p*p4}NpeqCQ8Ek`}y%+*tv)U%~|59`>DY22nMa=Oma}?aGh#flwJGM&v zy4VilY^k{}1xoLHJ$9lOSWW^ zJ19I+zKZ>q`T=?pXHTC8hi4x#bhLwp5c_!_d=0~sID3)Ac72Q8dIh^Vn!RvyxddE^ h6XDiSJ+EQ>Cx%4ozjw)1>0Hh|`AwdYXXPDv_y3}7DN6tV literal 15086 zcmeI3J!l+96vyWz*-|B|kepJ7oPbaeaf%r1#%WTzN+DDP1WA#`oxxxgzA9i)AgQE6 zg$Tq1+}PmGMXs>BxDf*5CY%bpF#_Yp#>C$If2*0xXtlRH`*B~8f#;c>kN5uX&6_tL zIvdk4ljh<@qr7SU_{^9~#+YW)e$N^6x9aAU)BfX>F+ZupvifL<*$`15r%#Wwy8k_U z_Uz|VQ&ZngPEP(jF){H_^sLcn97@hBh%$Aw(dW#WGv702dU|@cZY-hvW@cuZ-~f}w z_g-V85Ym|UcFaR~z$;X4)qcp5{2Ltfk{EKB?Ik7IquWvRNz|=Lv`apIS1@IS*Cx)cT7(o3ii=nU@BY@r6 ztgsGt-iB#+hu!6`LVd}u)q(qao-eW<^42tQi?yG}Ygp}I%ZjaPXJ6`jjI5$R7&ZP> zvis`D`Hg_OH4x|c5k8(&fc-n!x5)Rx!a`Jqipa89yDC(*{go?MK0JQ>INIOeFGUX? zJcxA<)gd_tHrAh*r%+yCfByXWhp0k&@#00aw6s)6zFP-XVon{{QM)AmI2N%Mn2%6< zyMAfd-@JJfV*yVQ!taXOUpTlIUBY*Y#!S{J{_ZERU%!4m#<8-p5*48m*ds9GLuKL) z_>(>lb~iVJ%7vdZec}B!i67hJPlLkk5_VCDiX-zftiY_T6!hpX0uN_2c}&d7vmc-we%(ouV6~aDL+~RpJa3 zpWnv){H*yh<9vSs|G3{D(V)ObZ_jlEqVZOV8k2}0O zgL9YI+S-aSa}T1;t?%UB9qcXs52cYVt45uV;1>-ZOl3Hw$7&HE&Yy&T)_C}Bl&G( z)ZLh?#=Ik6G)BWT@V~sn_p~u>^2yVAi~5E!$(-ssQwwG(a@y3V;ObB>+(~_$o=$IP z2bm_qYd2>{XIFJRw)L^y`JGl%^tGt_JFPi=luU{pOY)T;M87MBABbLx-ddu3 zKpTDNTT;xaVe;KC#rqEYk);lpq$knG_PxW{Qw#$uv`3v6ALPEwl9$!SSa`rIP;A`I z>ij5+cab(>cob?2EBl}b|B$}IaFB0~-$Aywx1%iD-QA5gHa0RbIU5kGRL=ExWVhRG z|4*Zt<-2$9=E;w3K)jUv%(#}6eROn``FCX6u}_-q{W@e5v;DfXGWR~0&}(&dH3Cx> z&Ckz=$dC7uG?{)K^GQN4-FCKJe(b;aDMTCw z3+tSmZG530nOR2wyJjVl`DSc8gc>R81JUS&Yqw}?E*P^wx zwG-5AHoH6-!&niv>ee%MZ*MO?Qy(54Mn1vQ@2fI8clDbd{K7I^Fdp;Soe%~$10rhU$)|+aJ_f}D_k!906iM diff --git a/apps/spark/public/locales/de/translation.json b/apps/spark/public/locales/de/translation.json new file mode 100644 index 0000000..539b465 --- /dev/null +++ b/apps/spark/public/locales/de/translation.json @@ -0,0 +1,137 @@ +{ + "Button": { + "defaultText": "Weitere Infos", + "addToCart" : "Jetzt kaufen", + "addMoreCart" : "Weitere kaufen", + "downloadText": "Herunterladen" + }, + "CartList": { + "emptyText": "Dein Warnkorb ist leer.", + "product": "Produkt:", + "quantity": "Anzahl:", + "price": "Preis:", + "description": "Beschreibung:" + }, + "DetailedCart": { + "headline": "Warenkorb", + "emptyText": "Dein Warenkorb ist leer.", + "description": "Beschreibung", + "price": "Preis", + "quantity": "Anzahl", + "total": "Summe", + "checkoutButtonText": "Zur Kasse", + "continueShopping": "Weiter einkaufen", + "cartTotals": "Warenkorb Summe", + "subtotalInclTax": "Zwischensumme (inkl. MwSt.)", + "tax": "MwSt." + }, + "HeaderCart": { + "title": "Warenkorb" + }, + "HeaderSearchForm": { + "close": "Suche schließen", + "label": "Suchen", + "placeholder": "Suchen ...", + "submit": "Suchen" + }, + "Loading": { + "loading": "laden ..." + }, + "SideCart": { + "title": "Warenkorb", + "close": "Schließen", + "openCartButtonText": "Warenkorb anzeigen" + }, + "Ticker": { + "title": "Eilmeldung" + }, + "FacetFilters": { + "title": "Filter" + }, + "ProductAssets": { + "downloads": "Downloads" + }, + "Search": { + "Header": { + "title": "Suchergebnisse", + "message": "Ihre Suche nach {{query}} ergab {{totalCount}} Treffer." + } + }, + "SearchFilter": { + "closeSearch": "Suche schließen", + "filters": "Filter", + "type_CMArticle": "Stories", + "type_CMCategory": "Kategorien", + "type_CMChannel": "Seiten", + "type_CMEvent": "Events", + "type_CMExternalChannel": "External Channels", + "type_CMExternalPage": "Externe Seiten", + "type_CMExternalProduct": "Produkte", + "type_CMImageMap": "Image Maps", + "type_CMLook": "Looks", + "type_CMPerson": "Editors", + "type_CMPicture": "Bilder", + "type_CMProduct": "Produkte", + "type_CMProductTeaser": "Produkt Teaser", + "type_CMRecipe": "Rezepte", + "type_CMVideo": "Videos", + "allTypes": "Alle Typen,", + "subject": "Schlagwort", + "type": "Typ", + "price": "Preis", + "brand": "Marke" + }, + "SortFilter": { + "sortBy": "Sortieren nach", + "Relevance": "Relevanz", + "Display Date Asc": "Anzeige Datum (aufsteigend)", + "Display Date Desc": "Anzeige Datum (absteigend)", + "Creation Date Asc": "Erstellungsdatum (aufsteigend)", + "Creation Date Desc": "Erstellungsdatum (absteigend)", + "Modification Date Asc": "Änderungsdatum (aufsteigend)", + "Modification Date Desc": "Änderungsdatum (absteigend)" + }, + "DetailPage": { + "relatedProducts": "Produkte", + "related": "Ähnliche Inhalte" + }, + "CheckoutPage": { + "successTitle": "Checkout abgeschlossen", + "successMessage": "

Danke für Ihre Bestellung.

Unser Team ist gerade dabei, Ihre Bestellung zu verpacken und zu versenden.

Wir werden Sie informieren, sobald die Ware auf dem Weg zu Ihnen ist.

", + "continueShopping": "Weiter einkaufen" + }, + "CMArticle": "Story", + "CMCategory": "Category", + "CMChannel": "Page", + "CMEvent": "Event", + "CMExternalChannel": "External Channel", + "CMExternalPage": "External Page", + "CMExternalProduct": "Product", + "CMImageMap": "Image Map", + "CMLook": "Look", + "CMPerson": "Editor", + "CMPicture": "Picture", + "CMProduct": "Product", + "CMProductTeaser": "Product Teaser", + "CMRecipe": "Recipe", + "CMVideo": "Video", + "commonSize": "Size", + "color": "Color", + "style": "Style", + "gender": "Gender", + "season": "Season", + "landscape_ratio16x9": "Ausschnitt 16:9", + "portrait_ratio2x3": "Ausschnitt 2:3", + "landscape_ratio4x3": "Ausschnitt 4:3", + "landscape_ratio8x3": "Ausschnitt 8:3", + "portrait_ratio1x1": "Ausschnitt 1:1", + "OfferPrice_USD": "Preis", + "({* TO 100])": "Unter 100€", + "({100 TO 200])": "Zwischen 100€ und 200€", + "({200 TO 300])": "Zwischen 200€ und 300€", + "({300 TO 400])": "Zwischen 300€ und 400€", + "({400 TO 500])": "Zwischen 400€ und 500€", + "({500 TO *})": "Über 500€", + "mobile-portrait": "(orientation: portrait) and (max-width: 767px)", + "tablet-portrait": "(orientation: portrait) and (min-width: 768px)" +} diff --git a/apps/spark/public/locales/en/translation.json b/apps/spark/public/locales/en/translation.json new file mode 100644 index 0000000..27360c5 --- /dev/null +++ b/apps/spark/public/locales/en/translation.json @@ -0,0 +1,137 @@ +{ + "Button": { + "defaultText": "Read more", + "addToCart" : "Add to cart", + "addMoreCart" : "Add more", + "downloadText": "Download" + }, + "CartList": { + "emptyText": "Your cart is currently empty.", + "product": "Product:", + "quantity": "Quantity:", + "price": "Price:", + "description": "Description:" + }, + "DetailedCart": { + "headline": "Cart", + "emptyText": "Your cart is currently empty.", + "description": "Description", + "price": "Price", + "quantity": "Quantity", + "total": "Total", + "checkoutButtonText": "Checkout", + "continueShopping": "Continue Shopping", + "cartTotals": "Cart Totals", + "subtotalInclTax": "Subtotal (incl. tax)", + "tax": "Tax" + }, + "HeaderCart": { + "title": "Cart" + }, + "HeaderSearchForm": { + "close": "Close search", + "label": "Search", + "placeholder": "Search ...", + "submit": "Search" + }, + "Loading": { + "loading": "loading ..." + }, + "SideCart": { + "title": "Cart", + "close": "Close", + "openCartButtonText": "Go to Cart" + }, + "Ticker": { + "title": "Breaking News" + }, + "FacetFilters": { + "title": "Filters" + }, + "ProductAssets": { + "downloads": "Downloads" + }, + "Search": { + "Header": { + "title": "Search Results", + "message": "Your search for {{query}} returned {{totalCount}} hits." + } + }, + "SearchFilter": { + "closeSearch": "Close search", + "filters": "Filters", + "type_CMArticle": "Stories", + "type_CMCategory": "Categories", + "type_CMChannel": "Pages", + "type_CMEvent": "Events", + "type_CMExternalChannel": "External Channels", + "type_CMExternalPage": "External Pages", + "type_CMExternalProduct": "Products", + "type_CMImageMap": "Image Maps", + "type_CMLook": "Looks", + "type_CMPerson": "Editors", + "type_CMPicture": "Pictures", + "type_CMProduct": "Products", + "type_CMProductTeaser": "Product Teasers", + "type_CMRecipe": "Recipes", + "type_CMVideo": "Videos", + "allTypes": "All types", + "subject": "Tag", + "type": "Type", + "price": "Price", + "brand": "Brand" + }, + "SortFilter": { + "sortBy": "Sort by", + "Relevance": "Relevance", + "Display Date Asc": "Display Date (ascending)", + "Display Date Desc": "Display Date (descending)", + "Creation Date Asc": "Creation Date (ascending)", + "Creation Date Desc": "Creation Date (descending)", + "Modification Date Asc": "Modification Date (ascending)", + "Modification Date Desc": "Modification Date (descending)" + }, + "DetailPage": { + "relatedProducts": "Products", + "related": "Related" + }, + "CheckoutPage": { + "successTitle": "Checkout Completed", + "successMessage": "

Thank you for your order.

Our team is currently packing and shipping your order.
We will inform you as soon as the goods are on their way to you.

", + "continueShopping": "Continue Shopping" + }, + "CMArticle": "Story", + "CMCategory": "Category", + "CMChannel": "Page", + "CMEvent": "Event", + "CMExternalChannel": "External Channel", + "CMExternalPage": "External Page", + "CMExternalProduct": "Product", + "CMImageMap": "Image Map", + "CMLook": "Look", + "CMPerson": "Editor", + "CMPicture": "Picture", + "CMProduct": "Product", + "CMProductTeaser": "Product Teaser", + "CMRecipe": "Recipe", + "CMVideo": "Video", + "commonSize": "Size", + "color": "Color", + "style": "Style", + "gender": "Gender", + "season": "Season", + "landscape_ratio16x9": "Crop 16:9", + "portrait_ratio2x3": "Crop 2:3", + "landscape_ratio4x3": "Crop 4:3", + "landscape_ratio8x3": "Crop 8:3", + "portrait_ratio1x1": "Crop 1:1", + "OfferPrice_USD": "Price", + "({* TO 100])": "Less than $100", + "({100 TO 200])": "Between $100 and $200", + "({200 TO 300])": "Between $200 and $300", + "({300 TO 400])": "Between $300 and $400", + "({400 TO 500])": "Between $400 and $500", + "({500 TO *})": "More than $500", + "mobile-portrait": "(orientation: portrait) and (max-width: 767px)", + "tablet-portrait": "(orientation: portrait) and (min-width: 768px)" +} diff --git a/apps/spark/public/locales/fr/translation.json b/apps/spark/public/locales/fr/translation.json new file mode 100644 index 0000000..efed29b --- /dev/null +++ b/apps/spark/public/locales/fr/translation.json @@ -0,0 +1,137 @@ +{ + "Button": { + "defaultText": "En savoir plus", + "addToCart" : "Ajouter au panier", + "addMoreCart" : "Ajouter plus", + "downloadText": "Télécharger" + }, + "CartList": { + "emptyText": "Votre Panier es vide.", + "product": "Produit:", + "quantity": "Quantité:", + "price": "Prix:", + "description": "Description:" + }, + "DetailedCart": { + "headline": "Panier", + "emptyText": "Votre Panier est vide.", + "description": "Description", + "price": "Prix", + "quantity": "Quantité", + "total": "Total", + "checkoutButtonText": "Aller à la caisse", + "continueShopping": "Continuer les achats", + "cartTotals": "Totaux du panier", + "subtotalInclTax": "Sous-total (TTC)", + "tax": "Taxe" + }, + "HeaderCart": { + "title": "Panier" + }, + "HeaderSearchForm": { + "close": "Fermer la recherche", + "label": "Recherche", + "placeholder": "Rechercher ...", + "submit": "Rechercher" + }, + "Loading": { + "loading": "chargement ..." + }, + "SideCart": { + "title": "Panier d'achat", + "close": "Fermer", + "openCartButtonText": "Aller au panier" + }, + "Ticker": { + "title": "Breaking News" + }, + "FacetFilters": { + "title": "Filtre" + }, + "ProductAssets": { + "downloads": "Téléchargements" + }, + "Search": { + "Header": { + "title": "Search Results", + "message": "Your search for {{query}} returned {{totalCount}} hits." + } + }, + "SearchFilter": { + "closeSearch": "Fermer la recherche", + "filters": "Filtres", + "type_CMArticle": "Stories", + "type_CMCategory": "Categories", + "type_CMChannel": "Pages", + "type_CMEvent": "Events", + "type_CMExternalChannel": "External Channels", + "type_CMExternalPage": "External Pages", + "type_CMExternalProduct": "Products", + "type_CMImageMap": "Image Maps", + "type_CMLook": "Looks", + "type_CMPerson": "Editors", + "type_CMPicture": "Pictures", + "type_CMProduct": "Products", + "type_CMProductTeaser": "Product Teasers", + "type_CMRecipe": "Recipes", + "type_CMVideo": "Videos", + "allTypes": "Tous les types", + "subject": "Étiquette", + "type": "Type", + "price": "prix", + "brand": "Marque" + }, + "SortFilter": { + "sortBy": "Trier par", + "Relevance": "Pertinence", + "Display Date Asc": "Date d'affichage (croissant)", + "Display Date Desc": "Date d'affichage (décroissant)", + "Creation Date Asc": "Date de création (croissante)", + "Creation Date Desc": "Date de création (décroissant)", + "Modification Date Asc": "Date de modification (croissante)", + "Modification Date Desc": "Date de modification (décroissant)" + }, + "DetailPage": { + "relatedProducts": "Produits", + "related": "Contenu connexe" + }, + "CheckoutPage": { + "successTitle": "Checkout terminé", + "successMessage": "

Merci pour votre commande.

Notre équipe est actuellement en train d'emballer et d'expédier votre commande.
Nous vous informerons dès que les marchandises seront en route vers vous.

", + "continueShopping": "Poursuivre les achats" + }, + "CMArticle": "Story", + "CMCategory": "Category", + "CMChannel": "Page", + "CMEvent": "Event", + "CMExternalChannel": "External Channel", + "CMExternalPage": "External Page", + "CMExternalProduct": "Product", + "CMImageMap": "Image Map", + "CMLook": "Look", + "CMPerson": "Editor", + "CMPicture": "Picture", + "CMProduct": "Product", + "CMProductTeaser": "Product Teaser", + "CMRecipe": "Recipe", + "CMVideo": "Video", + "commonSize": "Size", + "color": "Color", + "style": "Style", + "gender": "Gender", + "season": "Season", + "landscape_ratio16x9": "Crop 16:9", + "portrait_ratio2x3": "Crop 2:3", + "landscape_ratio4x3": "Crop 4:3", + "landscape_ratio8x3": "Crop 8:3", + "portrait_ratio1x1": "Crop 1:1", + "OfferPrice_USD": "Price", + "({* TO 100])": "Less than $100", + "({100 TO 200])": "Between $100 and $200", + "({200 TO 300])": "Between $200 and $300", + "({300 TO 400])": "Between $300 and $400", + "({400 TO 500])": "Between $400 and $500", + "({500 TO *})": "More than $500", + "mobile-portrait": "(orientation: portrait) and (max-width: 767px)", + "tablet-portrait": "(orientation: portrait) and (min-width: 768px)" +} diff --git a/apps/spark/public/locales/it/translation.json b/apps/spark/public/locales/it/translation.json new file mode 100644 index 0000000..b51c9c0 --- /dev/null +++ b/apps/spark/public/locales/it/translation.json @@ -0,0 +1,137 @@ +{ + "Button": { + "defaultText": "Scorpi di più", + "addToCart" : "Aggiungi al carrello", + "addMoreCart" : "Aggiungere altro", + "downloadText": "Scaricare" + }, + "CartList": { + "emptyText": "La shopping bag è vuota.", + "product": "Prodotto:", + "quantity": "Quantità:", + "price": "Prezzo:", + "description": "Descrizione:" + }, + "DetailedCart": { + "headline": "Shopping Bag", + "emptyText": "La shopping bag è vuota.", + "description": "Descrizione", + "price": "Prezzo", + "quantity": "Quantità", + "total": "Totale", + "checkoutButtonText": "Cassa", + "continueShopping": "Continua lo shopping", + "cartTotals": "Totali del carrello", + "subtotalInclTax": "Subtotale (tasse incluse)", + "tax": "Tassa" + }, + "HeaderCart": { + "title": "Carrello" + }, + "HeaderSearchForm": { + "close": "Chiudi la ricerca", + "label": "Ricerca", + "placeholder": "Cerca ...", + "submit": "Cerca" + }, + "Loading": { + "loading": "caricamento ..." + }, + "SideCart": { + "title": "Carrello", + "close": "Chiudere", + "openCartButtonText": "Vai al carrello" + }, + "Ticker": { + "title": "Ultime notizie" + }, + "FacetFilters": { + "title": "Filtro" + }, + "ProductAssets": { + "downloads": "Scaricamenti" + }, + "Search": { + "Header": { + "title": "Search Results", + "message": "Your search for {{query}} returned {{totalCount}} hits." + } + }, + "SearchFilter": { + "closeSearch": "Chiudere la ricerca", + "filters": "Filtri", + "type_CMArticle": "Stories", + "type_CMCategory": "Categories", + "type_CMChannel": "Pages", + "type_CMEvent": "Events", + "type_CMExternalChannel": "External Channels", + "type_CMExternalPage": "External Pages", + "type_CMExternalProduct": "Products", + "type_CMImageMap": "Image Maps", + "type_CMLook": "Looks", + "type_CMPerson": "Editors", + "type_CMPicture": "Pictures", + "type_CMProduct": "Products", + "type_CMProductTeaser": "Product Teasers", + "type_CMRecipe": "Recipes", + "type_CMVideo": "Videos", + "allTypes": "Tutti i tipi", + "subject": "Tag", + "type": "Tipo", + "price": "Prezzo", + "brand": "Segno" + }, + "SortFilter": { + "sortBy": "Ordina per", + "Relevance": "Rilevanza", + "Display Date Asc": "Data di visualizzazione (ascendente)", + "Display Date Desc": "Data di visualizzazione (decrescente)", + "Creation Date Asc": "Data di creazione (ascendente)", + "Creation Date Desc": "Data di creazione (decrescente)", + "Modification Date Asc": "Data di modifica (ascendente)", + "Modification Date Desc": "Data di modifica (decrescente)" + }, + "DetailPage": { + "relatedProducts": "Prodotti", + "related": "Contenuto relativo" + }, + "CheckoutPage": { + "successTitle": "Checkout completato", + "successMessage": "

Grazie per il suo ordine.

Il nostro team sta attualmente imballando e spedendo il suo ordine.
La informeremo non appena la merce sarà in viaggio verso di lei.

", + "continueShopping": "Continua lo shopping" + }, + "CMArticle": "Story", + "CMCategory": "Category", + "CMChannel": "Page", + "CMEvent": "Event", + "CMExternalChannel": "External Channel", + "CMExternalPage": "External Page", + "CMExternalProduct": "Product", + "CMImageMap": "Image Map", + "CMLook": "Look", + "CMPerson": "Editor", + "CMPicture": "Picture", + "CMProduct": "Product", + "CMProductTeaser": "Product Teaser", + "CMRecipe": "Recipe", + "CMVideo": "Video", + "commonSize": "Size", + "color": "Color", + "style": "Style", + "gender": "Gender", + "season": "Season", + "landscape_ratio16x9": "Crop 16:9", + "portrait_ratio2x3": "Crop 2:3", + "landscape_ratio4x3": "Crop 4:3", + "landscape_ratio8x3": "Crop 8:3", + "portrait_ratio1x1": "Crop 1:1", + "OfferPrice_USD": "Price", + "({* TO 100])": "Less than $100", + "({100 TO 200])": "Between $100 and $200", + "({200 TO 300])": "Between $200 and $300", + "({300 TO 400])": "Between $300 and $400", + "({400 TO 500])": "Between $400 and $500", + "({500 TO *})": "More than $500", + "mobile-portrait": "(orientation: portrait) and (max-width: 767px)", + "tablet-portrait": "(orientation: portrait) and (min-width: 768px)" +} diff --git a/apps/spark/public/logo192.png b/apps/spark/public/logo192.png deleted file mode 100644 index fc44b0a3796c0e0a64c3d858ca038bd4570465d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5347 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 b{|{}U^kRn2wo}j7|0ATu<;8xA7zX}7|B6mN diff --git a/apps/spark/public/manifest.json b/apps/spark/public/manifest.json index 080d6c7..1f2f141 100644 --- a/apps/spark/public/manifest.json +++ b/apps/spark/public/manifest.json @@ -6,16 +6,6 @@ "src": "favicon.ico", "sizes": "64x64 32x32 24x24 16x16", "type": "image/x-icon" - }, - { - "src": "logo192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "logo512.png", - "type": "image/png", - "sizes": "512x512" } ], "start_url": ".", diff --git a/apps/spark/src/components/App/App.tsx b/apps/spark/src/components/App/App.tsx index 7b502f5..03cd18b 100644 --- a/apps/spark/src/components/App/App.tsx +++ b/apps/spark/src/components/App/App.tsx @@ -4,6 +4,7 @@ import { ApolloProvider } from "@apollo/client"; import { HelmetProvider } from "react-helmet-async"; import { ThemeProvider } from "styled-components"; import { SiteContextProvider } from "../../context/SiteContextProvider"; +import CartContextProvider from "../../context/CartContext"; import { getRootSegment, isAPQEnabled, setLogLevel } from "../../utils/App/App"; import PreviewPage from "../../pages/PreviewPage"; import { initializeApollo } from "../../utils/App/Apollo"; @@ -44,27 +45,32 @@ const App: FC = () => { - - - - - - - {isPreview() && } - {isPreview() && ( - - )} + + + + + + + + {isPreview() && } + {isPreview() && ( + + )} - - - - - - - + + + + + + + + diff --git a/apps/spark/src/components/App/AppRoutes.tsx b/apps/spark/src/components/App/AppRoutes.tsx index 6058cb1..330b63b 100644 --- a/apps/spark/src/components/App/AppRoutes.tsx +++ b/apps/spark/src/components/App/AppRoutes.tsx @@ -5,8 +5,10 @@ import Page from "../../pages/Page"; import ProductPage from "../../pages/ProductPage"; import CategoryPage from "../../pages/CategoryPage"; import SearchPage from "../../pages/SearchPage"; +import CartPage from "../../pages/CartPage"; import TopicPage from "../../pages/TopicPage"; import AuthorPage from "../../pages/AuthorPage"; +import CheckoutPage from "../Checkout/CheckoutPage"; /** * The site specific routes of the app @@ -15,6 +17,10 @@ import AuthorPage from "../../pages/AuthorPage"; const AppRoutes: FC = () => { return ( + {/* Cart */} + + {/* Checkout */} + {/* Search */} {/* Tag */} diff --git a/apps/spark/src/components/App/GlobalStyle.tsx b/apps/spark/src/components/App/GlobalStyle.tsx index 0dbcb93..052c0a3 100644 --- a/apps/spark/src/components/App/GlobalStyle.tsx +++ b/apps/spark/src/components/App/GlobalStyle.tsx @@ -17,22 +17,84 @@ export const GlobalStyle = createGlobalStyle` --font-size-text: 16px; --font-size-text-small: 14px; --line-height: 1.2rem; - /* COLORS */ - --color-background-light: #fff; - --color-background-dark: #1a1a1a; + + /* COLORS - primary */ + --color-red: #dd342b; + --color-magenta: #d82eb4; + --color-dark-grey: #363936; + + /* COLORS - secondary */ + --color-purple: #672779; + --color-blue: #006cae; + --color-turquoise: #6fc3b8; + --color-green: #2fac66; + --color-yellow: #efdf0f; + --color-light-grey: #f4f4f4; + --color-black: #000; + --color-white: #fff; + + --color-background-light: var(--color-white); + --color-background-dark: var(--color-dark-grey); --color-background-grey: #333; - --color-background-light-grey: #efefed; - --color-menu-shadow: hsla(0, 0%, 0%, 0.5); - --color-background-image: #ccc; - --color-green-highlight: #6fc3b8; - --color-green-highlight-hover: var(--color-background-dark); - --color-green-highlight-active: var(--color-background-grey); - --color-font-cta-hover: var(--color-background-light); + --color-background-light-grey: var(--color-light-grey); + --color-background-image: var(--color-light-grey); + + --color-green-highlight: #bbff00; + --color-green-highlight-hover: #ddff00; + --color-green-highlight-active: var(--color-green-highlight-hover); + + /* GRADIENTS - primary */ + --gradient-red-to-magenta: linear-gradient(135deg, var(--color-red), var(--color-magenta)); + --gradient-purple-to-blue: linear-gradient(135deg, var(--color-purple), var(--color-blue)); + --gradient-magenta-to-purple: linear-gradient(135deg, var(--color-magenta), var(--color-purple)); + + /* GRADIENTS - secondary */ + --gradient-turquoise-to-purple: linear-gradient(135deg, var(--color-turquoise), var(--color-purple)); + --gradient-blue-to-green: linear-gradient(135deg, var(--color-blue), var(--color-green)); + --gradient-yellow-to-red: linear-gradient(135deg, var(--color-yellow), var(--color-red)); + --gradient-blue-to-turquoise: linear-gradient(135deg, var(--color-blue), var(--color-turquoise)); + --gradient-dark-to-light-grey: linear-gradient(135deg, var(--color-dark-grey), var(--color-light-grey)); + --gradient-light-to-dark-grey: linear-gradient(135deg, var(--color-light-grey), var(--color-dark-grey)); + /* SIZES */ --padding-small: 12px; --padding-medium: 24px; --padding-large: 48px; --screen-size-max: 1140px; + + /* BORDERS */ + --border-radius-small: 3px; + --border-radius-medium: 6px; + --border-radius-large: 9px; + --border-width-small: 1px; + --border-width-medium: 2px; + --border-width-large: 5px; + + /* CTA buttons */ + --cta-background: var(--color-white); + --cta-text-color: var(--color-black); + --cta-border: var(--border-width-small) solid var(--cta-text-color); + --cta-border-radius: var(--border-radius-small); + --cta-background-hover: var(--color-light-grey); + --cta-text-color-hover: var(--cta-text-color); + --cta-border-hover: var(--border-width-small) solid var(--color-light-grey); + --cta-background-active: var(--color-light-grey); + --cta-text-color-active: var(--cta-text-color); + --cta-border-active: var(--border-width-small) solid var(--color-light-grey); + + --cta-primary-background: var(--color-black); + --cta-primary-text-color: var(--color-white); + --cta-primary-border: var(--border-width-small) solid var(--color-black); + --cta-primary-border-radius: var(--border-radius-small); + --cta-primary-background-hover: var(--color-light-grey); + --cta-primary-text-color-hover: var(--color-black); + --cta-primary-border-hover: var(--border-width-small) solid var(--color-light-grey); + --cta-primary-background-active: var(--color-light-grey); + --cta-primary-text-color-active: var(--cta-primary-text-color); + --cta-primary-border-active: var(--border-width-small) solid var(--color-light-grey); + + /* Shadows */ + --drop-shadow: 0px 0px 20px rgba(0,0,0,0.25); } @font-face { diff --git a/apps/spark/src/components/Button/Button.tsx b/apps/spark/src/components/Button/Button.tsx index 57217aa..a3960f4 100644 --- a/apps/spark/src/components/Button/Button.tsx +++ b/apps/spark/src/components/Button/Button.tsx @@ -1,40 +1,51 @@ import React from "react"; +import { useTranslation } from "react-i18next"; import styled from "styled-components"; import Link from "../Link/Link"; interface Props { - linkTarget: any; + linkTarget?: any; + clickHandler?: () => void; text?: string; additionalClass?: string; openInNewTab?: boolean; externalLink?: boolean; + primary?: boolean; } -export const StyledButton = styled(Link)` - display: inline-block; +export const StyledButton = styled.div<{ primary?: boolean }>` + background: ${(props) => (props.primary ? "var(--cta-primary-background)" : "var(--cta-background)")}; + border-radius: ${(props) => (props.primary ? "var(--cta-primary-border-radius)" : "var(--cta-border-radius)")}; + border: ${(props) => (props.primary ? "var(--cta-primary-border)" : "var(--cta-border)")}; + color: ${(props) => (props.primary ? "var(--cta-primary-text-color)" : "var(--cta-text-color)")}; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + font-family: var(--font-family-headline); + font-size: var(--font-size-heading-3); + padding: 10px 20px 5px; + pointer-events: auto; position: relative; text-decoration: none; - color: #000; - background-color: var(--color-green-highlight); - border-radius: 0; - pointer-events: auto; text-transform: uppercase; - padding: 10px 20px 5px; - transition: all 0.1s ease; - font-size: var(--font-size-heading-3); - font-family: var(--font-family-headline); + transition: all 0.5s ease; + &:hover { - background-color: var(--color-green-highlight-hover); - color: var(--color-font-cta-hover); + background: ${(props) => (props.primary ? "var(--cta-primary-background-hover)" : "var(--cta-background-hover)")}; + border: ${(props) => (props.primary ? "var(--cta-primary-border-hover)" : "var(--cta-border-hover)")}; + color: ${(props) => (props.primary ? "var(--cta-primary-text-color-hover)" : "var(--cta-text-color-hover)")}; } &:active, &:focus { outline: none; - background-color: var(--color-green-highlight-active); + background: ${(props) => (props.primary ? "var(--cta-primary-background-active)" : "var(--cta-background-active)")}; + border: ${(props) => (props.primary ? "var(--cta-primary-border-active)" : "var(--cta-border-active)")}; + color: ${(props) => (props.primary ? "var(--cta-primary-text-color-active)" : "var(--cta-text-color-active)")}; box-shadow: - inset 0 0 0 1px #fff, - inset 0 0 0 2px #000; + inset 0 0 0 1px var(--cta-background-active), + inset 0 0 0 2px var(--cta-text-color-active); } & + & { @@ -42,36 +53,32 @@ export const StyledButton = styled(Link)` } `; -export const CMButton = styled.div` - font-family: var(--font-family-text); - font-size: var(--font-size-text-small); - line-height: 1.428571429; - cursor: pointer; - text-decoration: none; - background-color: hsla(0, 0%, 100%, 0.75); - border: none; - border-radius: 0; - &:hover { - background-color: #fff; - } - &:active, - &:focus { - background-color: #fff; - box-shadow: - inset 0 0 0 1px hsla(0, 0%, 100%, 0.75), - inset 0 0 0 2px #000; - } -`; +const Button: React.FC = ({ + linkTarget, + clickHandler, + text, + additionalClass, + openInNewTab = false, + externalLink = false, + primary = true, +}) => { + const { t } = useTranslation(); -const Button: React.FC = ({ linkTarget, text, additionalClass, openInNewTab = false, externalLink = false }) => { - text = text ? text : "Read more"; //todo add i18n + if (!text) { + // do not show default text "read more" for media / download links + text = + linkTarget && linkTarget.indexOf("/caas/v1/media") === 0 ? t("Button.downloadText") : t("Button.defaultText"); + } return ( {text} diff --git a/apps/spark/src/components/CTA/CTA.tsx b/apps/spark/src/components/CTA/CTA.tsx index 4467bb2..936ab8b 100644 --- a/apps/spark/src/components/CTA/CTA.tsx +++ b/apps/spark/src/components/CTA/CTA.tsx @@ -8,6 +8,7 @@ interface Props { targets?: Array; additionalClass?: string; additionalButtonClass?: string; + primary?: boolean; } export const StyledCTA = styled.div` @@ -17,7 +18,7 @@ export const StyledCTA = styled.div` text-shadow: none; `; -const CTA: React.FC = ({ targets, additionalClass, additionalButtonClass }) => { +const CTA: React.FC = ({ targets, additionalClass, additionalButtonClass, primary = true }) => { return ( {targets && @@ -32,6 +33,7 @@ const CTA: React.FC = ({ targets, additionalClass, additionalButtonClass additionalClass={additionalButtonClass} openInNewTab={target.openInNewTab} externalLink={target.externalLink} + primary={primary} /> ) ); diff --git a/apps/spark/src/components/Cart/CartList.tsx b/apps/spark/src/components/Cart/CartList.tsx new file mode 100644 index 0000000..078a29c --- /dev/null +++ b/apps/spark/src/components/Cart/CartList.tsx @@ -0,0 +1,136 @@ +import React from "react"; +import { useTranslation } from "react-i18next"; +import styled, { css } from "styled-components"; +import { useCartContextState } from "../../context/CartContext"; +import ProductPricing from "../Product/ProductPricing"; +import { metaDataProperty } from "../../utils/Preview/MetaData"; +import Link from "../Link/Link"; +import Image from "../Media/Image"; + +const Cart = styled.div``; +const EmptyCart = styled.div` + margin-bottom: 8px; + width: 200px; + padding: 12px 0; + border-bottom: 1px solid #eeeeee; +`; +const CartItem = styled.div` + padding: 10px 0; + border-bottom: 1px solid #eeeeee; + margin-bottom: 10px; + display: flex; +`; +const ItemPicture = styled.div` + flex: 0 0 60px; +`; +const ItemProperties = styled.div` + padding-left: 10px; + flex: 2; +`; +const ItemRemove = styled.div` + flex: 0; + cursor: pointer; +`; +const Property = styled.div<{ hideName: boolean }>` + > div { + display: inline-block; + font-size: var(--font-size-text-small); + + > a { + color: #000; + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } + } + + ${(props) => + props.hideName && + css` + > div:first-child { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; + } + `} +`; +const TitleProperty = styled(Property)` + font-size: var(--font-size-text-small); + margin-bottom: 6px; +`; +const DescriptionProperty = styled(Property)` + display: none; +`; +const QuantityProperty = styled(Property)``; +const PriceProperty = styled(Property)` + display: inline-block; + float: right; + padding-right: 20px; +`; +const CartList: React.FC = () => { + const { cartItems, itemCount, removeProduct } = useCartContextState(); + const { t } = useTranslation(); + return ( + + {itemCount === 0 && {t("CartList.emptyText")}} + {itemCount > 0 && ( +
+ {cartItems.map((item, index) => { + return ( + + {item.product.picture && ( + + + + )} + + +
{t("CartList.product")}
+
+ {item.product.title} +
+
+ +
{t("CartList.quantity")}
+
{item.quantity}
+
+ +
{t("CartList.price")}
+
+ +
+
+ +
{t("CartList.description")}
+
{item.product.text}
+
+
+ + {item.quantity > 0 && ( + + )} + +
+ ); + })} +
+ )} +
+ ); +}; + +export default CartList; diff --git a/apps/spark/src/components/Cart/DetailedCart.tsx b/apps/spark/src/components/Cart/DetailedCart.tsx new file mode 100644 index 0000000..1a4d8a6 --- /dev/null +++ b/apps/spark/src/components/Cart/DetailedCart.tsx @@ -0,0 +1,279 @@ +import React, { useEffect } from "react"; +import { useTranslation } from "react-i18next"; +import styled, { css } from "styled-components"; +import { useCartContextState } from "../../context/CartContext"; +import Link from "../Link/Link"; +import ProductPricing, { formatPrice } from "../Product/ProductPricing"; +import { metaDataProperty } from "../../utils/Preview/MetaData"; +import Image, { StyledImage } from "../Media/Image"; +import Button, { StyledButton } from "../Button/Button"; +import { Headline } from "../Details/Detail"; +import { StyledCol } from "../PageGrid/Col"; +import QuantityButton, { CartQuantity } from "../Product/QuantityButton"; +import { useSiteContextState } from "../../context/SiteContextProvider"; +import BasketIcon from "./assets/basket.svg"; + +const Cart = styled.div` + display: flex; + + > div { + } +`; + +const EmptyCart = styled.div` + text-align: center; +`; + +const CartProducts = styled.div` + flex: 2; + padding-right: 12px; + + table { + border-collapse: collapse; + + thead { + height: 3em; + th { + &:nth-child(3) { + text-align: start; + } + } + } + + tbody > tr { + border-bottom: 1px solid var(--color-background-light-grey); + + &:last-child { + border: none; + } + + th { + text-align: center; + } + + td { + font-size: 14px; + padding: 0.5em 0.5em 1em 0; + + @media only screen and (max-width: 767px) { + padding: 30px 12px 30px 12px; + } + + // remove btn + :first-child { + ${StyledButton} { + padding: 0 8px; + aspect-ratio: 1/1; + border-color: transparent; + } + } + + // product thumbnail + :nth-child(2) { + width: 150px; + aspect-ratio: 1/1; + + ${StyledImage} { + border-radius: var(--border-radius-small); + } + } + + // product name + :nth-child(3) { + width: 340px; + font-family: var(--font-family-headline); + font-size: var(--font-size-heading-3); + + a { + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } + } + + // price + :nth-child(4) { + width: 100px; + text-align: end; + } + + // quantity + :nth-child(5) { + width: 150px; + ${CartQuantity} { + min-width: 130px; + } + } + + // total + :last-child { + width: 100px; + text-align: end; + + span { + color: #262626; + font-size: 16px; + } + } + } + } + } +`; +const CartCheckout = styled.div` + flex: 1; + background: #f9f9f9; + padding: 30px; + + h2 { + margin-top: 0; + } + + > div { + & > * { + flex: 1; + } + } +`; + +const CartContent = styled.div<{ addBorder?: boolean }>` + display: flex; + ${(props) => + props.addBorder && props.addBorder === true + ? css` + border-top: 1px solid #dbdbdb; + padding: 20px 0 0 0; + margin: 20px 0 37px 0; + ` + : css` + margin: 24px 0 6px; + `} +`; + +const DetailedCart: React.FC = () => { + const { rootSegment } = useSiteContextState(); + const { cartItems, itemCount, increase, decrease, removeProduct, total, hideSideCart } = useCartContextState(); + const { t } = useTranslation(); + + useEffect(() => { + hideSideCart(); + }, []); + + return ( + + {t("DetailedCart.headline")} + {itemCount === 0 && ( + + +

{t("DetailedCart.emptyText")}

+ + + + + {isInCart(banner) && ( + + )} + {!isInCart(banner) && ( + + )} )} diff --git a/apps/spark/src/components/Product/assets/wish-outline.svg b/apps/spark/src/components/Product/assets/wish-outline.svg new file mode 100644 index 0000000..85c0a55 --- /dev/null +++ b/apps/spark/src/components/Product/assets/wish-outline.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/spark/src/components/Product/assets/wish-solid.svg b/apps/spark/src/components/Product/assets/wish-solid.svg new file mode 100644 index 0000000..7831c26 --- /dev/null +++ b/apps/spark/src/components/Product/assets/wish-solid.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/spark/src/components/Product/assets/wish.svg b/apps/spark/src/components/Product/assets/wish.svg deleted file mode 100644 index 801c38e..0000000 --- a/apps/spark/src/components/Product/assets/wish.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/spark/src/components/Search/Filters/SearchFilter.tsx b/apps/spark/src/components/Search/Filters/SearchFilter.tsx index aa1e041..8c771ba 100644 --- a/apps/spark/src/components/Search/Filters/SearchFilter.tsx +++ b/apps/spark/src/components/Search/Filters/SearchFilter.tsx @@ -1,5 +1,6 @@ import React from "react"; import styled, { css } from "styled-components"; +import { useTranslation } from "react-i18next"; import { SearchFacet, useSearchStateContextState } from "../../../context/SearchStateContext"; import Chevron from "../assets/chevron.svg"; import ArrowBack from "../assets/arrow-back.svg"; @@ -117,11 +118,12 @@ const SearchFilter: React.FC = ({ title, entries, filterType = "checkbox" const { removeFacets, selectedFacets } = useSearchStateContextState(); const [isOpen, setIsOpen] = React.useState(true); + const { t } = useTranslation(); return ( setIsOpen(!isOpen)}> - {title} + {t(title)}
@@ -134,7 +136,7 @@ const SearchFilter: React.FC = ({ title, entries, filterType = "checkbox" }} > - All types + {t("SearchFilter.allTypes")} )} {entries?.map((item, index) => { @@ -144,7 +146,7 @@ const SearchFilter: React.FC = ({ title, entries, filterType = "checkbox" diff --git a/apps/spark/src/components/Search/Filters/StringFilterEntry.tsx b/apps/spark/src/components/Search/Filters/StringFilterEntry.tsx index e432d4d..1add1fb 100644 --- a/apps/spark/src/components/Search/Filters/StringFilterEntry.tsx +++ b/apps/spark/src/components/Search/Filters/StringFilterEntry.tsx @@ -1,5 +1,6 @@ import React from "react"; import { useSearchStateContextState } from "../../../context/SearchStateContext"; +import { getLocalizedLabel } from "../../../utils/Translation/TranslationHelper"; import { isActiveGroup, isFacetValueSelected, @@ -31,7 +32,8 @@ const StringFilterEntry: React.FC = ({ title, label, query, count }) => { > {!isSelected && ( - {label} + {/*TODO: Get localized tag label*/} + {title === "subject" ? label : getLocalizedLabel(title + "_" + label, "SearchFilter")} {count && count > 0 && {count}} )} diff --git a/apps/spark/src/components/Search/HeaderSearchForm.tsx b/apps/spark/src/components/Search/HeaderSearchForm.tsx index ce48174..354ae0d 100644 --- a/apps/spark/src/components/Search/HeaderSearchForm.tsx +++ b/apps/spark/src/components/Search/HeaderSearchForm.tsx @@ -1,11 +1,11 @@ import React, { FC, useEffect, useState } from "react"; import { useHistory, useLocation } from "react-router-dom"; +import { useTranslation } from "react-i18next"; import styled from "styled-components"; import { useSuggestLazyQuery } from "@coremedia-labs/graphql-layer"; import { useSearchStateContextState } from "../../context/SearchStateContext"; import Hamburger from "../Header/Hamburger"; import { useSiteContextState } from "../../context/SiteContextProvider"; -import { ApolloClientAlert } from "../Error/Alert"; import { LanguageChooserMenu } from "../Header/LanguageChooser"; import { SearchButton, SearchFormFieldSet, SearchFormLabel, SearchInput } from "./SearchQuery"; @@ -110,7 +110,9 @@ const StyledSearch = styled.div` `; const HeaderInput = styled(SearchInput)` - background-color: #fff; + background-color: var(--color-background-light-grey); + border: none; + box-shadow: none; @media screen and (max-width: 767px), screen and (min-width: 768px) and (max-width: 1199px) and (orientation: portrait) { @@ -194,10 +196,11 @@ const HeaderSearchForm: FC = () => { const { rootSegment } = useSiteContextState(); const location = useLocation(); const { setQuery } = useSearchStateContextState(); + const { t } = useTranslation(); const [suggestions, setSuggestions] = useState>([]); - const [getSuggestionQuery, { error }] = useSuggestLazyQuery(); + const [getSuggestionQuery, {}] = useSuggestLazyQuery(); const { siteId } = useSiteContextState(); const onChangeHandler = (text: string) => { @@ -242,8 +245,6 @@ const HeaderSearchForm: FC = () => { setSearchQuery(urlSearchParams.get("query") || ""); }, [location.search]); - if (error) return ; - return ( { /> - Search + {t("HeaderSearchForm.label")} onChangeHandler(event.target.value)} type="search" name="query" - placeholder="Search..." + placeholder={t("HeaderSearchForm.placeholder")} required={true} minLength={3} //onBlur={() => setSuggestions([])} value={searchQuery} /> - - Search + + {t("HeaderSearchForm.submit")} 0}> {suggestions && diff --git a/apps/spark/src/components/Search/Search.tsx b/apps/spark/src/components/Search/Search.tsx index ac601fe..41f47a3 100644 --- a/apps/spark/src/components/Search/Search.tsx +++ b/apps/spark/src/components/Search/Search.tsx @@ -1,5 +1,6 @@ import React from "react"; import styled from "styled-components"; +import { useTranslation } from "react-i18next"; import { useSearchPageContextState } from "../../context/SearchPageContext"; import { useSearchStateContextState } from "../../context/SearchStateContext"; import { StyledCol } from "../PageGrid/Col"; @@ -49,16 +50,16 @@ const SearchHeader = styled.div` const Search: React.FC = () => { const { totalCount } = useSearchPageContextState(); const { query } = useSearchStateContextState(); - + const { t } = useTranslation(); return ( -

Search Results

+

{t("Search.Header.title")}

{query && ( -
- Your search for {query} returned {totalCount} hits. -
+
)}
diff --git a/apps/spark/src/components/Search/SearchFilters.tsx b/apps/spark/src/components/Search/SearchFilters.tsx index f23ddc2..02f5bf2 100644 --- a/apps/spark/src/components/Search/SearchFilters.tsx +++ b/apps/spark/src/components/Search/SearchFilters.tsx @@ -1,5 +1,6 @@ import React, { useState } from "react"; import styled, { css } from "styled-components"; +import { useTranslation } from "react-i18next"; import SortFilter from "./SortFilter"; import FacetFilters from "./Filters/FacetFilters"; import FilterIcon from "./assets/filter.svg"; @@ -87,7 +88,7 @@ const SearchFilterPopupHead = styled.div<{ active: boolean }>` const SearchFilterButton = styled.button` position: relative; text-decoration: none; - color: var(--color-font-cta-hover); + color: var(--color-cta-font-hover); background-color: var(--color-green-highlight); border-radius: 0; pointer-events: auto; @@ -100,7 +101,7 @@ const SearchFilterButton = styled.button` &:hover { background-color: var(--color-green-highlight-hover); - color: var(--color-font-cta-hover); + color: var(--color-cta-font-hover); } &:active, @@ -118,6 +119,7 @@ const SearchFilterButton = styled.button` const SearchFilters: React.FC = () => { const [toggled, setToggled] = useState(false); + const { t } = useTranslation(); return ( <> @@ -128,13 +130,13 @@ const SearchFilters: React.FC = () => { }} > - Filters + {t("SearchFilters.filters")} -

Filters

+

{t("SearchFilters.filters")}

diff --git a/apps/spark/src/components/Search/SearchResult.tsx b/apps/spark/src/components/Search/SearchResult.tsx index 162e3c5..b669b7d 100644 --- a/apps/spark/src/components/Search/SearchResult.tsx +++ b/apps/spark/src/components/Search/SearchResult.tsx @@ -7,34 +7,37 @@ import { notEmpty } from "../../utils/Helpers"; import SearchBanner from "./SearchBanner"; export const MoreButton = styled.button` + background: var(--cta-background); + border-radius: var(--cta-border-radius); + border: var(--cta-border); + color: var(--cta-text-color); + cursor: pointer; display: block; + font-family: var(--font-family-headline); + font-size: var(--font-size-heading-3); margin: 0 auto; - border: none; - cursor: pointer; + padding: 10px 20px 5px; + pointer-events: auto; position: relative; text-decoration: none; - color: var(--color-font-cta-hover); - background-color: var(--color-green-highlight); - border-radius: 0; - pointer-events: auto; text-transform: uppercase; - padding: 10px 20px 5px; transition: all 0.1s ease; - font-size: var(--font-size-heading-3); - font-family: var(--font-family-headline); &:hover { - background-color: var(--color-green-highlight-hover); - color: var(--color-font-cta-hover); + background-color: var(--cta-background-hover); + border: var(--cta-border-hover); + color: var(--cta-text-color-hover); } &:active, &:focus { outline: none; - background-color: var(--color-green-highlight-active); + background: var(--cta-background-active); + border: var(--cta-border-active); + color: var(--cta-primary-text-color-active) " : " var(--cta-text-color-active); box-shadow: - inset 0 0 0 1px #fff, - inset 0 0 0 2px #000; + inset 0 0 0 1px var(--cta-background-active), + inset 0 0 0 2px var(--cta-text-color-active); } `; diff --git a/apps/spark/src/components/Search/SortFilter.tsx b/apps/spark/src/components/Search/SortFilter.tsx index d2e65f5..3fa7b5b 100644 --- a/apps/spark/src/components/Search/SortFilter.tsx +++ b/apps/spark/src/components/Search/SortFilter.tsx @@ -2,7 +2,9 @@ import React, { ChangeEvent, useMemo } from "react"; import { SortFieldWithOrder } from "@coremedia-labs/graphql-layer"; import { useHistory, useLocation } from "react-router-dom"; import styled from "styled-components"; +import { useTranslation } from "react-i18next"; import { useSearchStateContextState } from "../../context/SearchStateContext"; +import { getLocalizedLabel } from "../../utils/Translation/TranslationHelper"; const StyledSort = styled.div` height: 74px; @@ -35,6 +37,7 @@ const SortFilter: React.FC = () => { const urlSearchParams = useMemo(() => new URLSearchParams(location.search), [location.search]); const { setSortField, sortField, sortFields } = useSearchStateContextState(); + const { t } = useTranslation(); const onSortChange = (e: ChangeEvent): void => { e.preventDefault(); @@ -53,12 +56,12 @@ const SortFilter: React.FC = () => { <> {sortFields && ( - +