@wayke-se/components-react 3.2.0 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -155,7 +155,9 @@ const SearchProvider = ({ url, apiKey, useQueryParamsFromUrl, pathRoute, childre
155
155
  setQueryFilter({
156
156
  searchParams: initialQueryParams,
157
157
  });
158
- replaceState(`${window.location.pathname}${nextSearch}`);
158
+ if (useQueryParamsFromUrl) {
159
+ replaceState(`${window.location.pathname}${nextSearch}`);
160
+ }
159
161
  }
160
162
  setInitialize(true);
161
163
  }
@@ -0,0 +1,76 @@
1
+ import styled, { css } from 'styled-components';
2
+ import { size } from '../../layout/helpers';
3
+ export const Column = styled.div `
4
+ flex: 0 1 auto;
5
+
6
+ ${({ grow }) => grow &&
7
+ css `
8
+ flex-grow: 1;
9
+ `}
10
+
11
+ ${({ noShrink }) => noShrink &&
12
+ css `
13
+ flex-shrink: 0;
14
+ `}
15
+ `;
16
+ export const Columns = styled.div `
17
+ display: flex;
18
+ align-items: flex-start;
19
+
20
+ ${({ valign }) => valign === 'end'
21
+ ? css `
22
+ align-items: flex-end;
23
+ `
24
+ : valign === 'center'
25
+ ? css `
26
+ align-items: center;
27
+ `
28
+ : css `
29
+ align-items: flex-start;
30
+ `}
31
+
32
+ ${({ align }) => align === 'end'
33
+ ? css `
34
+ justify-content: flex-end;
35
+ `
36
+ : align === 'center'
37
+ ? css `
38
+ justify-content: center;
39
+ `
40
+ : css `
41
+ justify-content: flex-start;
42
+ `}
43
+
44
+ ${({ $spacing }) => $spacing &&
45
+ css `
46
+ margin: ${size($spacing / -2)};
47
+
48
+ & > ${Column} {
49
+ padding: ${size($spacing / 2)};
50
+ }
51
+ `}
52
+
53
+ ${({ flexWrap }) => flexWrap &&
54
+ css `
55
+ flex-wrap: wrap;
56
+ `}
57
+
58
+ ${({ flexInline }) => flexInline &&
59
+ css `
60
+ display: inline-flex;
61
+ `}
62
+
63
+ ${({ clearLtSm }) => clearLtSm &&
64
+ css `
65
+ ${(props) => props.theme.breakpoint.LtSm} {
66
+ display: block;
67
+ }
68
+ `}
69
+
70
+ ${({ clearLtMd }) => clearLtMd &&
71
+ css `
72
+ ${(props) => props.theme.breakpoint.LtMd} {
73
+ display: block;
74
+ }
75
+ `}
76
+ `;
@@ -3,7 +3,7 @@ import { List, Item, Value, Label } from './wrapper';
3
3
  import { VisualHeading } from '../Heading/index';
4
4
  import { Price, OldPrice } from '../Price/index';
5
5
  import { numberSeparator } from '../../utils/formats';
6
- const PriceTable = ({ price, oldPrice }) => (React.createElement(List, null,
6
+ const PriceTable = ({ price, discount }) => (React.createElement(List, null,
7
7
  React.createElement(Item, null,
8
8
  React.createElement(Label, null,
9
9
  React.createElement(VisualHeading, null, "Pris")),
@@ -11,10 +11,10 @@ const PriceTable = ({ price, oldPrice }) => (React.createElement(List, null,
11
11
  React.createElement(Price, null,
12
12
  numberSeparator(price),
13
13
  " kr"))),
14
- oldPrice !== undefined && (React.createElement(Item, null,
14
+ discount !== undefined && (React.createElement(Item, null,
15
15
  React.createElement(Label, null),
16
16
  React.createElement(Value, null,
17
17
  React.createElement(OldPrice, null,
18
- numberSeparator(oldPrice),
18
+ numberSeparator(price + discount),
19
19
  " kr"))))));
20
20
  export default PriceTable;
@@ -0,0 +1,23 @@
1
+ import styled, { css } from 'styled-components';
2
+ import { size } from '../../layout/helpers';
3
+ export const StateIndicator = styled.div `
4
+ width: ${size(1)};
5
+ height: ${size(1)};
6
+ border-radius: 50%;
7
+
8
+ ${({ $tone }) => $tone === 'success'
9
+ ? css `
10
+ background-color: ${(props) => props.theme.color.ui.positive};
11
+ `
12
+ : $tone === 'pending'
13
+ ? css `
14
+ background-color: ${(props) => props.theme.color.ui.neutral};
15
+ `
16
+ : $tone === 'error'
17
+ ? css `
18
+ background-color: ${(props) => props.theme.color.ui.negative};
19
+ `
20
+ : css `
21
+ background-color: ${(props) => props.theme.color.textDarkLighten};
22
+ `}
23
+ `;
@@ -13,6 +13,7 @@ const _colors = {
13
13
  redLight: '#ffd0d0',
14
14
  red: '#c71f1f',
15
15
  yellowLight: '#fff4c7',
16
+ yellow: '#ffc700',
16
17
  blueLight: '#daf7fc',
17
18
  },
18
19
  };
@@ -35,6 +36,7 @@ const theme = {
35
36
  positiveLight: _colors.ui.greenLight,
36
37
  positive: _colors.ui.green,
37
38
  neutralLight: _colors.ui.yellowLight,
39
+ neutral: _colors.ui.yellow,
38
40
  negativeLight: _colors.ui.redLight,
39
41
  negative: _colors.ui.red,
40
42
  infoLight: _colors.ui.blueLight,
@@ -2,12 +2,17 @@ import React, { useState, useCallback, useEffect } from 'react';
2
2
  import { Repeat, RepeatTiny } from '../../components/Repeat/index';
3
3
  import ActionList from '../../components/ActionList/index';
4
4
  import { ButtonPrimary, ButtonContent, ButtonInline } from '../../components/Button/index';
5
+ import { Columns, Column } from '../../components/Columns/index';
6
+ import { UtilityFontSizeSmall } from '../../components/Utility/index';
7
+ import { StateIndicator } from '../../components/StateIndicator/index';
5
8
  import CheckMarkList, { CheckMarkListItem } from '../../components/CheckMarkList/index';
6
9
  import Content from '../../components/Content/index';
7
10
  import SwitchBar from '../../components/SwitchBar/index';
8
11
  import BranchModal from './BranchModal';
9
12
  import PackageOptionModal from './PackageOptionModal';
10
- const CheckList = ({ manufacturer, packageOptions, ecommerce, branch, contact, toggleEcomModal, loadingCentralStorageVehicle, }) => {
13
+ import { format } from 'date-fns/esm';
14
+ import sv from 'date-fns/locale/sv';
15
+ const CheckList = ({ manufacturer, packageOptions, ecommerce, branch, contact, availableFrom, toggleEcomModal, loadingCentralStorageVehicle, }) => {
11
16
  const [modalBranch, setModalBranch] = useState(false);
12
17
  const openModalBranch = useCallback(() => setModalBranch(true), []);
13
18
  const closeModalBranch = useCallback(() => setModalBranch(false), []);
@@ -23,31 +28,6 @@ const CheckList = ({ manufacturer, packageOptions, ecommerce, branch, contact, t
23
28
  return (React.createElement(React.Fragment, null,
24
29
  modalBranch && (React.createElement(BranchModal, { loading: loadingCentralStorageVehicle, connections: branch?.connections, onClose: closeModalBranch })),
25
30
  modal && React.createElement(PackageOptionModal, { packageOption: modal, onClose: onClose }),
26
- React.createElement(Repeat, null,
27
- React.createElement(CheckMarkList, null,
28
- packageOption?.title && (React.createElement(CheckMarkListItem, null,
29
- React.createElement(React.Fragment, null,
30
- "Inkl.",
31
- ' ',
32
- React.createElement(ButtonInline, { onClick: () => onOpen({
33
- title: packageOption?.title,
34
- image: packageOption?.image,
35
- description: packageOption?.description,
36
- link: packageOption?.link,
37
- }) }, packageOption.title),
38
- ' ',
39
- "begagnatgaranti"))),
40
- packageOptions?.map((packageOption, index) => (React.createElement(CheckMarkListItem, { key: packageOption.title || index },
41
- React.createElement(React.Fragment, null,
42
- "Inkl.",
43
- ' ',
44
- React.createElement(ButtonInline, { onClick: () => onOpen({
45
- title: packageOption?.title,
46
- image: packageOption?.image,
47
- description: packageOption?.description,
48
- link: packageOption?.link,
49
- }) }, packageOption.title))))),
50
- ecommerce?.withHomeDelivery && React.createElement(CheckMarkListItem, null, "Hemleverans"))),
51
31
  React.createElement(Repeat, null,
52
32
  ecommerce && ecommerce.enabled && (React.createElement(RepeatTiny, null,
53
33
  React.createElement(ButtonPrimary, { disabled: !!ecommerce.reserved, fullWidth: true, onClick: toggleEcomModal },
@@ -57,6 +37,40 @@ const CheckList = ({ manufacturer, packageOptions, ecommerce, branch, contact, t
57
37
  React.createElement(Content, null,
58
38
  React.createElement("p", null, "Denna bil \u00E4r reserverad av en annan k\u00F6pare."))))),
59
39
  React.createElement(ActionList, { branch: branch, contact: contact })),
40
+ React.createElement(Repeat, null,
41
+ availableFrom && new Date(availableFrom).valueOf() > new Date().valueOf() && (React.createElement(RepeatTiny, null,
42
+ React.createElement(Columns, { "$spacing": 1, valign: "center" },
43
+ React.createElement(Column, { noShrink: true },
44
+ React.createElement(StateIndicator, { "$tone": "pending" })),
45
+ React.createElement(Column, null,
46
+ React.createElement(UtilityFontSizeSmall, null,
47
+ "Tillg\u00E4nglig fr\u00E5n ",
48
+ format(new Date(availableFrom), 'dd MMMM yyyy', { locale: sv })))))),
49
+ React.createElement(RepeatTiny, null,
50
+ React.createElement(CheckMarkList, null,
51
+ packageOption?.title && (React.createElement(CheckMarkListItem, null,
52
+ React.createElement(React.Fragment, null,
53
+ "Inkl.",
54
+ ' ',
55
+ React.createElement(ButtonInline, { onClick: () => onOpen({
56
+ title: packageOption?.title,
57
+ image: packageOption?.image,
58
+ description: packageOption?.description,
59
+ link: packageOption?.link,
60
+ }) }, packageOption.title),
61
+ ' ',
62
+ "begagnatgaranti"))),
63
+ packageOptions?.map((packageOption, index) => (React.createElement(CheckMarkListItem, { key: packageOption.title || index },
64
+ React.createElement(React.Fragment, null,
65
+ "Inkl.",
66
+ ' ',
67
+ React.createElement(ButtonInline, { onClick: () => onOpen({
68
+ title: packageOption?.title,
69
+ image: packageOption?.image,
70
+ description: packageOption?.description,
71
+ link: packageOption?.link,
72
+ }) }, packageOption.title))))),
73
+ ecommerce?.withHomeDelivery && React.createElement(CheckMarkListItem, null, "Hemleverans")))),
60
74
  (branch?.connections.length || 0) > 1 && (React.createElement(Repeat, null,
61
75
  React.createElement(SwitchBar, { title: "Centrallagerbil", actionTitle: "Byt anl\u00E4ggning", onClick: openModalBranch },
62
76
  React.createElement(Content, null,
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import Modal from '../../components/Modal/index';
3
+ import Content from '../../components/Content/index';
4
+ const DemoCarModal = ({ onClose }) => (React.createElement(Modal, { title: "Demobil", onClose: onClose },
5
+ React.createElement(Content, null,
6
+ React.createElement("p", null, "En demobil \u00E4r en bil som st\u00E5tt i utst\u00E4llning eller som p\u00E5 annat s\u00E4tt anv\u00E4nts f\u00F6r att visa upp en viss modell. Bilarna \u00E4r ofta v\u00E4lutrustade och har blivit v\u00E4l omh\u00E4ndertagna. Dessutom har de vanligtvis g\u00E5tt f\u00E5 mil och har fortfarande nybilsgarantierna kvar."))));
7
+ export default DemoCarModal;
@@ -1,4 +1,4 @@
1
- import React, { useMemo, useRef, useCallback, useEffect } from 'react';
1
+ import React, { useMemo, useRef, useCallback, useState, useEffect } from 'react';
2
2
  import WaykeEcomWeb from '@wayke-se/ecom-web';
3
3
  import Container from '../../components/Container/index';
4
4
  import UspList from '../../components/UspList/index';
@@ -31,6 +31,7 @@ import Page404 from './Page404';
31
31
  import PageLoading from './PageLoading';
32
32
  import PubSub from '../../utils/pubsub/pubsub';
33
33
  import Property from './Property';
34
+ import DemoCarModal from './DemoCarModal';
34
35
  import PdfDownloadContainer from '../../components/Pdf/index';
35
36
  import useSettings from '../../State/Settings/useSettings';
36
37
  const WaykeSearchItem = ({ id, hashRoute, pathRoute, disableResetScrollOnInit, placeholderImage, modifyDocumentTitleItem, onClickSearchItem, }) => {
@@ -38,6 +39,8 @@ const WaykeSearchItem = ({ id, hashRoute, pathRoute, disableResetScrollOnInit, p
38
39
  const ecomContext = useRef();
39
40
  const { loading, data: result } = useSearchItem(id);
40
41
  const { vehicle: centralStorageVehicle, loading: loadingCentralStorageVehicle } = useCentralStorage(result?.vehicle);
42
+ const [demoCarModal, setDemoCarModal] = useState(false);
43
+ const onToggleDemoCarModal = useCallback(() => setDemoCarModal(!demoCarModal), [demoCarModal]);
41
44
  useEffect(() => {
42
45
  if (ecomSettings) {
43
46
  ecomContext.current = new WaykeEcomWeb({
@@ -84,7 +87,7 @@ const WaykeSearchItem = ({ id, hashRoute, pathRoute, disableResetScrollOnInit, p
84
87
  const { vehicle } = result;
85
88
  const contact = centralStorageVehicle?.contact;
86
89
  const branch = centralStorageVehicle?.branch;
87
- const { title, shortDescription, media, description, price, financialOptions, manufacturer, ecommerce, packageOptions, publishedAt, documents, } = vehicle;
90
+ const { title, shortDescription, media, description, price, discount, financialOptions, manufacturer, ecommerce, packageOptions, publishedAt, documents, availableFrom, flags, } = vehicle;
88
91
  const insuranceOptions = centralStorageVehicle?.insuranceOptions
89
92
  ? centralStorageVehicle.insuranceOptions
90
93
  : vehicle.insuranceOptions;
@@ -93,10 +96,16 @@ const WaykeSearchItem = ({ id, hashRoute, pathRoute, disableResetScrollOnInit, p
93
96
  {
94
97
  title: modelYear,
95
98
  },
96
- {
97
- title: `${numberSeparator(mileage)} mil`,
98
- },
99
99
  ];
100
+ if (flags?.demoVersion) {
101
+ uspList.push({
102
+ title: 'Demobil',
103
+ onClick: onToggleDemoCarModal,
104
+ });
105
+ }
106
+ uspList.push({
107
+ title: `${numberSeparator(mileage)} mil`,
108
+ });
100
109
  if (gearbox) {
101
110
  uspList.push({ title: gearbox });
102
111
  }
@@ -126,12 +135,12 @@ const WaykeSearchItem = ({ id, hashRoute, pathRoute, disableResetScrollOnInit, p
126
135
  React.createElement(RepeatSmall, null,
127
136
  React.createElement(UspList, { small: true, items: uspList })))),
128
137
  React.createElement(ProductPageAsideSection, { mobileOrder: 2 },
129
- React.createElement(PriceTable, { price: price })),
138
+ React.createElement(PriceTable, { price: price, discount: discount || undefined })),
130
139
  (financialOptions.length > 0 || insuranceOptions.length > 0) && (React.createElement(ProductPageAsideSection, { mobileOrder: 4 },
131
140
  financialOptions.length > 0 && (React.createElement(FinancialOptions, { id: id, financialOptions: financialOptions })),
132
141
  insuranceOptions.length > 0 && (React.createElement(InsuranceOptions, { id: id, branch: centralStorageVehicle?.branch, insuranceOptions: insuranceOptions })))),
133
142
  React.createElement(ProductPageAsideSection, { mobileOrder: 5 },
134
- React.createElement(CheckList, { manufacturer: manufacturer, packageOptions: packageOptions, ecommerce: ecommerce, branch: branch, contact: centralStorageVehicle?.contact, loadingCentralStorageVehicle: loadingCentralStorageVehicle, toggleEcomModal: () => ecomContext.current?.start() }))),
143
+ React.createElement(CheckList, { manufacturer: manufacturer, packageOptions: packageOptions, ecommerce: ecommerce, branch: branch, contact: centralStorageVehicle?.contact, loadingCentralStorageVehicle: loadingCentralStorageVehicle, availableFrom: availableFrom, toggleEcomModal: () => ecomContext.current?.start() }))),
135
144
  React.createElement(ProductPageMain, null,
136
145
  React.createElement(ProductPageAsideSection, { mobileOrder: 3 },
137
146
  React.createElement(Gallery, { media: media, placeholderImage: placeholderImage })),
@@ -176,6 +185,7 @@ const WaykeSearchItem = ({ id, hashRoute, pathRoute, disableResetScrollOnInit, p
176
185
  React.createElement("p", null,
177
186
  "Priset \u00E4r ett cirkapris och baserat p\u00E5 ditt avtals antal m\u00E5nader och din ber\u00E4knade \u00E5rliga k\u00F6rstr\u00E4cka. Kostnad f\u00F6r f\u00F6rs\u00E4kring och serviceavtal tillkommer. Kontakta s\u00E4ljare f\u00F6r komplett kostnadsf\u00F6rslag.",
178
187
  ' ')))),
179
- React.createElement(PortalElement, { id: PortalNamespace.DefaultPortal })));
188
+ React.createElement(PortalElement, { id: PortalNamespace.DefaultPortal }),
189
+ demoCarModal && React.createElement(DemoCarModal, { onClose: onToggleDemoCarModal })));
180
190
  };
181
191
  export default WaykeSearchItem;
@@ -223,8 +223,13 @@ const SEARCH_ITEM_QUERY = gql `
223
223
  postalCode
224
224
  }
225
225
  price
226
+ discount
226
227
  shortDescription
227
228
  title
229
+ availableFrom
230
+ flags {
231
+ demoVersion
232
+ }
228
233
  }
229
234
  }
230
235
  ${HoursOpen}
@@ -291,6 +291,7 @@ export declare type Service = {
291
291
  };
292
292
  export declare type Vehicle = {
293
293
  __typename?: 'Vehicle';
294
+ availableFrom?: Maybe<Scalars['DateTime']>;
294
295
  branch?: Maybe<Branch>;
295
296
  contact?: Maybe<ContactOptions>;
296
297
  data: VehicleData;
@@ -339,5 +340,6 @@ export declare type VehicleDataPropertySetArgs = {
339
340
  export declare type VehicleFlags = {
340
341
  __typename?: 'VehicleFlags';
341
342
  auction?: Maybe<Scalars['Boolean']>;
343
+ demoVersion?: Maybe<Scalars['Boolean']>;
342
344
  testDrive?: Maybe<Scalars['Boolean']>;
343
345
  };
@@ -0,0 +1,16 @@
1
+ interface IColumn {
2
+ grow?: boolean;
3
+ noShrink?: boolean;
4
+ }
5
+ export declare const Column: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, IColumn, never>;
6
+ interface IColumns {
7
+ $spacing?: number;
8
+ flexWrap?: boolean;
9
+ flexInline?: boolean;
10
+ valign?: 'start' | 'center' | 'end';
11
+ align?: 'start' | 'center' | 'end';
12
+ clearLtSm?: boolean;
13
+ clearLtMd?: boolean;
14
+ }
15
+ export declare const Columns: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, IColumns, never>;
16
+ export {};
@@ -1,7 +1,7 @@
1
1
  /// <reference types="react" />
2
2
  interface PriceTableProps {
3
3
  price: number;
4
- oldPrice?: number;
4
+ discount?: number;
5
5
  }
6
- declare const PriceTable: ({ price, oldPrice }: PriceTableProps) => JSX.Element;
6
+ declare const PriceTable: ({ price, discount }: PriceTableProps) => JSX.Element;
7
7
  export default PriceTable;
@@ -0,0 +1,5 @@
1
+ interface StateIndicatorProps {
2
+ $tone?: 'success' | 'pending' | 'error';
3
+ }
4
+ export declare const StateIndicator: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, StateIndicatorProps, never>;
5
+ export {};
@@ -17,6 +17,7 @@ declare const theme: {
17
17
  positiveLight: string;
18
18
  positive: string;
19
19
  neutralLight: string;
20
+ neutral: string;
20
21
  negativeLight: string;
21
22
  negative: string;
22
23
  infoLight: string;
@@ -7,7 +7,8 @@ interface CheckList {
7
7
  branch?: Branch | null;
8
8
  contact?: ContactOptions | null;
9
9
  loadingCentralStorageVehicle: boolean;
10
+ availableFrom?: Date | null;
10
11
  toggleEcomModal: () => void;
11
12
  }
12
- declare const CheckList: ({ manufacturer, packageOptions, ecommerce, branch, contact, toggleEcomModal, loadingCentralStorageVehicle, }: CheckList) => JSX.Element;
13
+ declare const CheckList: ({ manufacturer, packageOptions, ecommerce, branch, contact, availableFrom, toggleEcomModal, loadingCentralStorageVehicle, }: CheckList) => JSX.Element;
13
14
  export default CheckList;
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ interface DemoCarModalProps {
3
+ onClose: () => void;
4
+ }
5
+ declare const DemoCarModal: ({ onClose }: DemoCarModalProps) => JSX.Element;
6
+ export default DemoCarModal;