diff --git a/packages/web-components/src/common/components/modal.svelte b/packages/web-components/src/common/components/modal.svelte index 58f0e27602..98179dc72d 100644 --- a/packages/web-components/src/common/components/modal.svelte +++ b/packages/web-components/src/common/components/modal.svelte @@ -2,6 +2,7 @@ import ClickOutSide from './click-out-side.svelte' export let isModalOpen export let toggleModal + export let title = 'Modal Title' {#if isModalOpen}
- +
+ + + +
{/if} diff --git a/packages/web-components/src/common/styles/__tests__/__snapshots__/index.ts.snap b/packages/web-components/src/common/styles/__tests__/__snapshots__/index.ts.snap index ef40787956..59859d7666 100644 --- a/packages/web-components/src/common/styles/__tests__/__snapshots__/index.ts.snap +++ b/packages/web-components/src/common/styles/__tests__/__snapshots__/index.ts.snap @@ -178,7 +178,7 @@ exports[`styles should generate a reset css class 1`] = `"css-h4w50h"`; exports[`styles should generate an object of CSS classes 1`] = ` Object { "bodyText": "css-11v9sqy", - "button": "css-naokd4", + "button": "css-1tgg1a8", "globalStyles": "css-ya093n", "input": "css-u6oic2", "offerBanner": "css-gl5ek3", diff --git a/packages/web-components/src/common/styles/__themes__/viewing-booking.js b/packages/web-components/src/common/styles/__themes__/viewing-booking.js new file mode 100644 index 0000000000..e593ae5b32 --- /dev/null +++ b/packages/web-components/src/common/styles/__themes__/viewing-booking.js @@ -0,0 +1,22 @@ +const defaultVariant = { + baseBackgroundColor: '#f9fbfd', + basefontSize: '16px', + basefontColor: '#12263f', + inverseFontColor: '#f9fbfd', + secondaryfontColor: '#1e2554', + primaryHeadingFontSize: '24px', + secondaryHeadingFontSize: '20px', + baseFontFamily: '"Roboto", sans-serif', + headingFontFamily: '"Open Sans", sans-serif', + primaryAccentColor: '#0061a8', + secondaryAccentColor: '#6c757d', + mapAccentColor: '#7bc9eb', + breakPoints: { + mobile: '', + tablet: '', + laptop: '', + desktop: '', + }, +} + +window.theme = defaultVariant diff --git a/packages/web-components/src/common/styles/theme.ts b/packages/web-components/src/common/styles/theme.ts index 0be18490a4..836cc2baba 100644 --- a/packages/web-components/src/common/styles/theme.ts +++ b/packages/web-components/src/common/styles/theme.ts @@ -118,16 +118,11 @@ export const generateThemeClasses = ( color: ${primaryAccentColor || '#000'}; border: 1px solid ${primaryAccentColor || 'grey'}; background: ${baseBackgroundColor || '#fff'}; - color: ${inverseFontColor || 'grey'}; &:hover { - background: ${inverseFontColor || 'grey'}; + background: ${primaryAccentColor || 'grey'}; color: ${baseBackgroundColor || '#fff'}; } - - &:last-child { - border-left: none; - } } `, input: css` diff --git a/packages/web-components/src/common/utils/__tests__/validate.ts b/packages/web-components/src/common/utils/__tests__/validate.ts new file mode 100644 index 0000000000..892b48f974 --- /dev/null +++ b/packages/web-components/src/common/utils/__tests__/validate.ts @@ -0,0 +1,19 @@ +import { validateEmail } from '../validate' + +describe('validate email', () => { + it('should return true', () => { + const mail = 'abc@edf.com' + expect(validateEmail(mail)).toBe(true) + }) + + it('should return false', () => { + let mail = 'abcedf.com' + expect(validateEmail(mail)).toBe(false) + + mail = 'abc@edf.c' + expect(validateEmail(mail)).toBe(false) + + mail = 'abc@edf' + expect(validateEmail(mail)).toBe(false) + }) +}) diff --git a/packages/web-components/src/common/utils/validate.ts b/packages/web-components/src/common/utils/validate.ts new file mode 100644 index 0000000000..60f2b800af --- /dev/null +++ b/packages/web-components/src/common/utils/validate.ts @@ -0,0 +1,5 @@ +export function validateEmail(email: string) { + //eslint-disable-next-line + const regex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + return regex.test(email) +} diff --git a/packages/web-components/src/scripts/rollup.config.viewing-booking.js b/packages/web-components/src/scripts/rollup.config.viewing-booking.js new file mode 100644 index 0000000000..39f081d9af --- /dev/null +++ b/packages/web-components/src/scripts/rollup.config.viewing-booking.js @@ -0,0 +1,30 @@ +import svelte from 'rollup-plugin-svelte' +import baseConfig from './rollup.config.base' +import replace from '@rollup/plugin-replace' +import path from 'path' + +const config = require(path.resolve(__dirname, '../..', 'config.json')) +const production = !process.env.ROLLUP_WATCH + +export default { + ...baseConfig, + input: 'src/viewing-booking/client/core/index.ts', + output: { + sourcemap: !production, + format: 'iife', + name: 'app', + file: './public/dist/viewing-booking.js', + }, + plugins: [ + svelte({ + dev: !production, + css: css => { + css.write('./public/dist/viewing-booking.css') + }, + }), + replace({ + 'process.env.NODE_ENV': JSON.stringify(config.NODE_ENV), + }), + ...baseConfig.plugins, + ], +} diff --git a/packages/web-components/src/search-widget/client/components/__tests__/__snapshots__/search-widget.ts.snap b/packages/web-components/src/search-widget/client/components/__tests__/__snapshots__/search-widget.ts.snap index f752b08d2a..455810fec2 100644 --- a/packages/web-components/src/search-widget/client/components/__tests__/__snapshots__/search-widget.ts.snap +++ b/packages/web-components/src/search-widget/client/components/__tests__/__snapshots__/search-widget.ts.snap @@ -152,7 +152,6 @@ exports[`search-widget it matches a snapshot 1`] = ` color: #000; border: 1px solid grey; background: #fff; - color: grey; } #search-widget .emotion-1:hover { @@ -160,10 +159,6 @@ exports[`search-widget it matches a snapshot 1`] = ` color: #fff; } -#search-widget .emotion-1:last-child { - border-left: none; -} - #search-widget .emotion-0 { font-family: Helvetica,Arial,sans-serif; font-size: 18px; diff --git a/packages/web-components/src/search-widget/client/components/__tests__/light-box/__snapshots__/enlarge-image-modal.test.ts.snap b/packages/web-components/src/search-widget/client/components/__tests__/light-box/__snapshots__/enlarge-image-modal.test.ts.snap index e2651c26bb..fa2ce6cf02 100644 --- a/packages/web-components/src/search-widget/client/components/__tests__/light-box/__snapshots__/enlarge-image-modal.test.ts.snap +++ b/packages/web-components/src/search-widget/client/components/__tests__/light-box/__snapshots__/enlarge-image-modal.test.ts.snap @@ -4,88 +4,111 @@ exports[`EnlargeImageModal should match snapshot 1`] = `
- Current carousel display image + + +
-
- - - - 1 - of - 10 - - - + + + 1 + of + 10 + + + + + + + + + + + +
+
diff --git a/packages/web-components/src/search-widget/client/components/__tests__/light-box/__snapshots__/widget.ts.snap b/packages/web-components/src/search-widget/client/components/__tests__/light-box/__snapshots__/widget.ts.snap index e2b5f1cc27..f1bcc369a4 100644 --- a/packages/web-components/src/search-widget/client/components/__tests__/light-box/__snapshots__/widget.ts.snap +++ b/packages/web-components/src/search-widget/client/components/__tests__/light-box/__snapshots__/widget.ts.snap @@ -4,88 +4,111 @@ exports[`Carousel should match snapshot 1`] = `
- Current carousel display image + + +
-
- - - - 1 - of - 10 - - - + + + 1 + of + 10 + + + + + + + + + + + +
+
diff --git a/packages/web-components/src/search-widget/client/core/__tests__/__snapshots__/index.ts.snap b/packages/web-components/src/search-widget/client/core/__tests__/__snapshots__/index.ts.snap index 517ea6679d..65fea9e659 100644 --- a/packages/web-components/src/search-widget/client/core/__tests__/__snapshots__/index.ts.snap +++ b/packages/web-components/src/search-widget/client/core/__tests__/__snapshots__/index.ts.snap @@ -66,7 +66,7 @@ Search_widget { "selectedProperty": null, "themeClasses": Object { "bodyText": "css-11v9sqy", - "button": "css-naokd4", + "button": "css-1tgg1a8", "globalStyles": "css-ya093n", "input": "css-u6oic2", "offerBanner": "css-gl5ek3", diff --git a/packages/web-components/src/viewing-booking/client/api/property.ts b/packages/web-components/src/viewing-booking/client/api/property.ts new file mode 100644 index 0000000000..d8e3f390df --- /dev/null +++ b/packages/web-components/src/viewing-booking/client/api/property.ts @@ -0,0 +1,10 @@ +import { PropertyData } from '../core' + +export const getProperty = async (): Promise => { + return Promise.resolve({ + image: + 'https://tracker.reapit.net/demo/_demo/webservice/rest/property/rps_demo-SCO190002/thumbnail?ApiKey=8ed799bbe77c96311e71f64b99ec2ddde765d13a&Width=480&Height=285&Crop=1', + address: 'Little Tingewick, Buckingham', + price: '£1,250,000', + }) +} diff --git a/packages/web-components/src/viewing-booking/client/components/__tests__/__snapshots__/viewing-booking.ts.snap b/packages/web-components/src/viewing-booking/client/components/__tests__/__snapshots__/viewing-booking.ts.snap new file mode 100644 index 0000000000..36ead59d7a --- /dev/null +++ b/packages/web-components/src/viewing-booking/client/components/__tests__/__snapshots__/viewing-booking.ts.snap @@ -0,0 +1,281 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`viewing-booking it matches a snapshot 1`] = ` +.emotion-6 html, +.emotion-6 body, +.emotion-6 div, +.emotion-6 span, +.emotion-6 applet, +.emotion-6 object, +.emotion-6 iframe, +.emotion-6 h1, +.emotion-6 h2, +.emotion-6 h3, +.emotion-6 h4, +.emotion-6 h5, +.emotion-6 h6, +.emotion-6 p, +.emotion-6 blockquote, +.emotion-6 pre, +.emotion-6 a, +.emotion-6 abbr, +.emotion-6 acronym, +.emotion-6 address, +.emotion-6 big, +.emotion-6 cite, +.emotion-6 code, +.emotion-6 del, +.emotion-6 dfn, +.emotion-6 em, +.emotion-6 img, +.emotion-6 ins, +.emotion-6 kbd, +.emotion-6 q, +.emotion-6 s, +.emotion-6 samp, +.emotion-6 small, +.emotion-6 strike, +.emotion-6 strong, +.emotion-6 sub, +.emotion-6 sup, +.emotion-6 tt, +.emotion-6 var, +.emotion-6 b, +.emotion-6 u, +.emotion-6 i, +.emotion-6 center, +.emotion-6 dl, +.emotion-6 dt, +.emotion-6 dd, +.emotion-6 menu, +.emotion-6 ol, +.emotion-6 ul, +.emotion-6 li, +.emotion-6 fieldset, +.emotion-6 form, +.emotion-6 label, +.emotion-6 legend, +.emotion-6 table, +.emotion-6 caption, +.emotion-6 tbody, +.emotion-6 tfoot, +.emotion-6 thead, +.emotion-6 tr, +.emotion-6 th, +.emotion-6 td, +.emotion-6 article, +.emotion-6 aside, +.emotion-6 canvas, +.emotion-6 details, +.emotion-6 embed, +.emotion-6 figure, +.emotion-6 figcaption, +.emotion-6 footer, +.emotion-6 header, +.emotion-6 hgroup, +.emotion-6 main, +.emotion-6 menu, +.emotion-6 nav, +.emotion-6 output, +.emotion-6 ruby, +.emotion-6 section, +.emotion-6 summary, +.emotion-6 time, +.emotion-6 mark, +.emotion-6 audio, +.emotion-6 video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} + +.emotion-6 article, +.emotion-6 aside, +.emotion-6 details, +.emotion-6 figcaption, +.emotion-6 figure, +.emotion-6 footer, +.emotion-6 header, +.emotion-6 hgroup, +.emotion-6 main, +.emotion-6 menu, +.emotion-6 nav, +.emotion-6 section { + display: block; +} + +.emotion-6 *[hidden] { + display: none; +} + +.emotion-6 body { + line-height: 1; +} + +.emotion-6 menu, +.emotion-6 ol, +.emotion-6 ul { + list-style: none; +} + +.emotion-6 blockquote, +.emotion-6 q { + quotes: none; +} + +.emotion-6 blockquote:before, +.emotion-6 blockquote:after, +.emotion-6 q:before, +.emotion-6 q:after { + content: ''; + content: none; +} + +.emotion-6 table { + border-collapse: collapse; + border-spacing: 0; +} + +.emotion-5 { + font-size: 14px; + font-family: "Roboto",sans-serif; + background: #f9fbfd; + color: #12263f; +} + +#appointment-bookings-viewing .emotion-2 { + font-family: "Open Sans",sans-serif; + font-size: 14px; + font-weight: bold; + color: #1e2554; + margin-bottom: 0.5em; +} + +#appointment-bookings-viewing .emotion-1 { + font-size: 14px; + font-family: "Roboto",sans-serif; + margin-bottom: 1em; +} + +#appointment-bookings-viewing .emotion-4 { + font-family: "Roboto",sans-serif; + font-size: 20px; + color: #0061a8; + border: 1px solid #0061a8; + background: #f9fbfd; +} + +#appointment-bookings-viewing .emotion-4:hover { + background: #0061a8; + color: #f9fbfd; +} + +#appointment-bookings-viewing .emotion-3 { + font-family: "Roboto",sans-serif; + font-size: 20px; + border: 1px solid #0061a8; +} + +.emotion-0 { + background: url(); +} + + +
+ + +
+
+
+ + + + + +
+
+
+ +
+ +`; diff --git a/packages/web-components/src/viewing-booking/client/components/__tests__/viewing-booking.ts b/packages/web-components/src/viewing-booking/client/components/__tests__/viewing-booking.ts new file mode 100644 index 0000000000..49869790b7 --- /dev/null +++ b/packages/web-components/src/viewing-booking/client/components/__tests__/viewing-booking.ts @@ -0,0 +1,33 @@ +import ViewingBooking from '../viewing-booking.svelte' +import { render } from '@testing-library/svelte' + +describe('viewing-booking', () => { + it('it matches a snapshot', () => { + const wrapper = render(ViewingBooking, { + apiKey: '', + parentSelector: '#appointment-bookings-viewing', + theme: { + baseBackgroundColor: '#f9fbfd', + basefontSize: '14px', + basefontColor: '#12263f', + inverseFontColor: '#f9fbfd', + secondaryfontColor: '#1e2554', + primaryHeadingFontSize: '24px', + secondaryHeadingFontSize: '20px', + baseFontFamily: '"Roboto", sans-serif', + headingFontFamily: '"Open Sans", sans-serif', + primaryAccentColor: '#0061a8', + secondaryAccentColor: '#1e2554', + mapAccentColor: '#7bc9eb', + breakPoints: { + mobile: '', + tablet: '', + laptop: '', + desktop: '', + }, + }, + }) + const { container } = wrapper + expect(container).toMatchSnapshot() + }) +}) diff --git a/packages/web-components/src/viewing-booking/client/components/viewing-booking.svelte b/packages/web-components/src/viewing-booking/client/components/viewing-booking.svelte new file mode 100644 index 0000000000..459e873ec3 --- /dev/null +++ b/packages/web-components/src/viewing-booking/client/components/viewing-booking.svelte @@ -0,0 +1,175 @@ + + + + + + + +
+
+

+ {propertyData && propertyData.address} + {propertyData && propertyData.price} +

+
+
+

To book a viewing, please enter your e-mail below.

+ + + {#if !correctEmail} + Please enter a valid e-mail address + {/if} +
+
+ +
+
+ +
diff --git a/packages/web-components/src/viewing-booking/client/core/__tests__/__snapshots__/index.ts.snap b/packages/web-components/src/viewing-booking/client/core/__tests__/__snapshots__/index.ts.snap new file mode 100644 index 0000000000..ea7955ac40 --- /dev/null +++ b/packages/web-components/src/viewing-booking/client/core/__tests__/__snapshots__/index.ts.snap @@ -0,0 +1,93 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ReactViewingWidgetComponent test match snapshot 1`] = ` +Viewing_booking { + "$$": Object { + "after_update": Array [], + "before_update": Array [], + "bound": Object {}, + "callbacks": Object {}, + "context": Map {}, + "ctx": Array [ + true, + true, + Object { + "address": "", + "image": "", + "price": "", + }, + "css-cb9zl5", + true, + Object { + "bodyText": "css-n0w2qa", + "button": "css-l8x1wu", + "globalStyles": "css-11c02ub", + "input": "css-1sj9ihm", + "offerBanner": "css-s4b31o", + "pagination": "css-1sys580", + "paginationActive": "css-1sys580", + "primaryHeading": "css-ayk9xy", + "primaryStrapline": "css-1d7j4w6", + "resultItem": "css-2mowv6", + "searchBox": "css-81h19r", + "secondaryHeading": "css-1qz6ie0", + "secondaryStrapline": "css-1kep8ws", + "selectedItem": "css-1w110sd", + }, + [Function], + [Function], + [Function], + Object { + "baseBackgroundColor": "#f9fbfd", + "baseFontFamily": "\\"Roboto\\", sans-serif", + "basefontColor": "#12263f", + "basefontSize": "14px", + "breakPoints": Object { + "desktop": "", + "laptop": "", + "mobile": "", + "tablet": "", + }, + "headingFontFamily": "\\"Open Sans\\", sans-serif", + "inverseFontColor": "#f9fbfd", + "mapAccentColor": "#7bc9eb", + "primaryAccentColor": "#0061a8", + "primaryHeadingFontSize": "24px", + "secondaryAccentColor": "#1e2554", + "secondaryHeadingFontSize": "20px", + "secondaryfontColor": "#1e2554", + }, + "", + "#appointment-bookings-viewing", + undefined, + ], + "dirty": Array [ + -1, + ], + "fragment": Object { + "c": [Function], + "d": [Function], + "i": [Function], + "l": [Function], + "m": [Function], + "o": [Function], + "p": [Function], + }, + "not_equal": [Function], + "on_destroy": Array [ + [Function], + ], + "on_mount": Array [], + "props": Object { + "apiKey": 10, + "parentSelector": 11, + "submitAction": 12, + "theme": 9, + }, + "update": [Function], + }, + "$capture_state": [Function], + "$inject_state": [Function], + "$set": [Function], +} +`; diff --git a/packages/web-components/src/viewing-booking/client/core/__tests__/index.ts b/packages/web-components/src/viewing-booking/client/core/__tests__/index.ts new file mode 100644 index 0000000000..b5f459770d --- /dev/null +++ b/packages/web-components/src/viewing-booking/client/core/__tests__/index.ts @@ -0,0 +1,32 @@ +import { ReapitViewingBookingComponent } from '../index' + +describe('ReactViewingWidgetComponent', () => { + it('test match snapshot', () => { + expect( + ReapitViewingBookingComponent({ + apiKey: '', + parentSelector: '#appointment-bookings-viewing', + theme: { + baseBackgroundColor: '#f9fbfd', + basefontSize: '14px', + basefontColor: '#12263f', + inverseFontColor: '#f9fbfd', + secondaryfontColor: '#1e2554', + primaryHeadingFontSize: '24px', + secondaryHeadingFontSize: '20px', + baseFontFamily: '"Roboto", sans-serif', + headingFontFamily: '"Open Sans", sans-serif', + primaryAccentColor: '#0061a8', + secondaryAccentColor: '#1e2554', + mapAccentColor: '#7bc9eb', + breakPoints: { + mobile: '', + tablet: '', + laptop: '', + desktop: '', + }, + }, + }), + ).toMatchSnapshot() + }) +}) diff --git a/packages/web-components/src/viewing-booking/client/core/__tests__/store.ts b/packages/web-components/src/viewing-booking/client/core/__tests__/store.ts new file mode 100644 index 0000000000..e1530ca0b2 --- /dev/null +++ b/packages/web-components/src/viewing-booking/client/core/__tests__/store.ts @@ -0,0 +1,36 @@ +import viewingBookingStore from '../store' + +describe('store', () => { + it('should return a default store', () => { + const expected = { + initializers: { + apiKey: '', + parentSelector: '', + theme: {}, + }, + email: '', + propertyData: { image: '', address: '', price: '' }, + isLoading: false, + themeClasses: { + globalStyles: '', + primaryHeading: '', + secondaryHeading: '', + primaryStrapline: '', + secondaryStrapline: '', + selectedItem: '', + bodyText: '', + button: '', + input: '', + resultItem: '', + searchBox: '', + offerBanner: '', + pagination: '', + paginationActive: '', + }, + } + const unsubscribe = viewingBookingStore.subscribe(store => { + expect(store).toEqual(expected) + }) + unsubscribe() + }) +}) diff --git a/packages/web-components/src/viewing-booking/client/core/index.ts b/packages/web-components/src/viewing-booking/client/core/index.ts new file mode 100644 index 0000000000..ef4bd0517e --- /dev/null +++ b/packages/web-components/src/viewing-booking/client/core/index.ts @@ -0,0 +1,27 @@ +import ViewingBooking from '../components/viewing-booking.svelte' +import { InitializerTheme } from '../../../common/styles/index' + +export interface PropertyData { + image: string + address: string + price: string +} +export interface ViewingBookingInitializers { + theme: Partial + apiKey: string + parentSelector: string +} + +export const ReapitViewingBookingComponent = ({ parentSelector, apiKey, theme }: ViewingBookingInitializers) => + new ViewingBooking({ + target: document.querySelector(parentSelector) || document.body, + props: { + theme, + apiKey, + parentSelector, + }, + }) + +Object.defineProperty(window, 'ReapitViewingBookingComponent', { + value: ReapitViewingBookingComponent, +}) diff --git a/packages/web-components/src/viewing-booking/client/core/store.ts b/packages/web-components/src/viewing-booking/client/core/store.ts new file mode 100644 index 0000000000..64a4949f8e --- /dev/null +++ b/packages/web-components/src/viewing-booking/client/core/store.ts @@ -0,0 +1,45 @@ +import { writable, Writable } from 'svelte/store' +import { ViewingBookingInitializers, PropertyData } from './index' +import { ThemeClasses } from '../../../common/styles' + +export interface ViewingBookingStore { + initializers: ViewingBookingInitializers + themeClasses: ThemeClasses + + email: string + propertyData: PropertyData + isLoading: boolean +} + +const viewBookingStore: Writable = writable({ + initializers: { + apiKey: '', + parentSelector: '', + theme: {}, + }, + themeClasses: { + globalStyles: '', + primaryHeading: '', + secondaryHeading: '', + primaryStrapline: '', + secondaryStrapline: '', + selectedItem: '', + bodyText: '', + button: '', + input: '', + resultItem: '', + searchBox: '', + offerBanner: '', + pagination: '', + paginationActive: '', + }, + email: '', + isLoading: false, + propertyData: { + image: '', + address: '', + price: '', + }, +}) + +export default viewBookingStore diff --git a/packages/web-components/src/viewing-booking/client/index.html b/packages/web-components/src/viewing-booking/client/index.html new file mode 100644 index 0000000000..6acc0a2169 --- /dev/null +++ b/packages/web-components/src/viewing-booking/client/index.html @@ -0,0 +1,34 @@ + + + + + Web Components + + + + + + Book a viewing +
+ + + + + +