PluginProbe ʕ •ᴥ•ʔ
Appointment Booking Plugin – LatePoint | Calendar & Scheduling for WordPress / 5.6.8
Appointment Booking Plugin – LatePoint | Calendar & Scheduling for WordPress v5.6.8
5.6.8 5.6.7 5.6.6 5.6.5 5.6.4 5.6.3 5.6.2 5.6.1 5.6.0 5.5.2 5.5.1 5.5.0 5.4.2 trunk 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.1.91 5.1.92 5.1.93 5.1.94 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1
latepoint / blocks / src / list-of-resources / edit.js
latepoint / blocks / src / list-of-resources Last commit date
block.json 1 month ago edit.js 2 weeks ago index-min.js 1 year ago index.js 1 year ago save.js 1 year ago
edit.js
874 lines
1 /**
2 * External dependencies
3 */
4 import styled from '@emotion/styled';
5
6 /**
7 * WordPress components that create the necessary UI elements for the block
8 *
9 * @see https://developer.wordpress.org/block-editor/packages/packages-components/
10 */
11 import {registerBlockType} from '@wordpress/blocks';
12 import {__} from '@wordpress/i18n';
13 import {
14 Panel,
15 PanelBody,
16 PanelRow,
17 TextControl,
18 SelectControl,
19 ToggleControl,
20 TabPanel,
21 __experimentalUnitControl as UnitControl,
22 } from '@wordpress/components';
23
24 import TypographyControl from "../../controls/TypographyControl";
25 import ColorSelectorControl from "../../controls/ColorSelectorControl";
26 import BorderControl from "../../controls/BorderControl";
27 import PaddingBoxControl from "../../controls/PaddingBoxControl";
28 import IframeEmotionCacheProvider from '../utils/IframeEmotionCacheProvider';
29 /**
30 * React hook that is used to mark the block wrapper element.
31 * It provides all the necessary props like the class name.
32 *
33 * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops
34 */
35 import {
36 useBlockProps,
37 InspectorControls,
38 } from '@wordpress/block-editor';
39 import {useState, useEffect} from "@wordpress/element";
40 import React from "react";
41 import {SettingsIcon, StylesIcon, CardIcon} from "../../controls/LatepointIcons";
42 import BoxShadowControl from "../../controls/BoxShadowControl";
43 import FontSizeControl from "../../controls/FontSizeControl";
44
45
46 const ListOfResourcesWrapper = styled.div`
47
48 `;
49
50 const LatepointBookButton = styled.div`
51 margin-top: 10px;
52 `;
53
54 const ListOfResources = styled.div`
55 display: grid;
56 gap: 30px;
57 grid-template-columns: 1fr 1fr 1fr 1fr;
58
59 &.resources-columns-1 {
60 grid-template-columns: 1fr;
61 grid-gap: 20px;
62 }
63
64 &.resources-columns-2 {
65 grid-template-columns: 1fr 1fr;
66 grid-gap: 50px;
67 }
68
69 &.resources-columns-3 {
70 grid-template-columns: 1fr 1fr 1fr;
71 grid-gap: 40px;
72 }
73
74 &.resources-columns-4 {
75 grid-template-columns: 1fr 1fr 1fr 1fr;
76 grid-gap: 30px;
77 }
78
79 &.resources-columns-5 {
80 grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
81 grid-gap: 20px;
82 }
83 `;
84
85 const Resource = styled.div`
86 padding: 20px;
87 background-color: #fff;
88 box-shadow: 0 2px 18px -6px rgba(0, 0, 0, 0.2), 0 1px 2px 0 rgba(0, 0, 0, 0.1);
89 transition: all 0.2s ease;
90 height: 100%;
91 overflow: hidden;
92 `;
93
94 const ResourceTitle = styled.h3`
95 margin: 10px 0;
96 font-size: 22px;
97 `;
98 const ResourceImage = styled.div`
99 padding-bottom: 75%;
100 position: relative;
101 margin: -20px -20px 25px;
102 `;
103 const ResourceDescription = styled.div`
104 color: #7c85a3;
105 font-size: 15px;
106 font-weight: 400;
107 margin-bottom: 10px;
108 line-height: 1.3;
109 `;
110 const ResourcePrice = styled.div`
111 font-weight: 600;
112 font-size: 15px;
113 margin-bottom: 10px;
114 `;
115
116 const PanelRowBlock = styled(PanelRow)`
117 display: block;
118 margin-bottom: 20px;
119 `;
120
121 const NoMatches = styled.div`
122 display: block;
123 padding: 20px;
124 background-color: #eee;
125 color: #888;
126 text-align: center;
127 `;
128 const Separator = styled.div`
129 height: 1px;
130 background-color: #e0e0e0;
131 `;
132
133 const btnHoverColor = (e, attributes, action) => {
134 if (attributes.is_inherit) {
135 return;
136 }
137
138 let current_el = e.currentTarget.style;
139 if (action === 'mouseEnter') {
140 if (attributes.bg_color_hover) current_el.backgroundColor = attributes.bg_color_hover;
141 if (attributes.border_color_hover) current_el.borderColor = attributes.border_color_hover;
142 if (attributes.text_color_hover) current_el.color = attributes.text_color_hover;
143 } else {
144 current_el.backgroundColor = attributes.button_bg_color;
145 current_el.borderColor = attributes.border_color;
146 current_el.color = attributes.button_text_color;
147 }
148 };
149 const cardHoverColor = (e, attributes, action) => {
150 if (attributes.is_inherit) {
151 return;
152 }
153 let current_el = e.currentTarget.style;
154 let price_el = e.currentTarget.querySelector('.lb-resource-price');
155 let title_el = e.currentTarget.querySelector('.lb-resource-title');
156 let descr_el = e.currentTarget.querySelector('.lb-resource-descr');
157 if (action === 'mouseEnter') {
158 if (title_el && attributes.card_text_color_hover) title_el.style.color = attributes.card_text_color_hover;
159 if (price_el && attributes.card_price_color_hover) price_el.style.color = attributes.card_price_color_hover;
160 if (descr_el && attributes.card_descr_color_hover) descr_el.style.color = attributes.card_descr_color_hover;
161 if (attributes.card_bg_color_hover) current_el.backgroundColor = attributes.card_bg_color_hover;
162 if (attributes.card_border_color_hover) current_el.borderColor = attributes.card_border_color_hover;
163 } else {
164 if (title_el && attributes.card_text_color) title_el.style.color = attributes.card_text_color;
165 if (price_el && attributes.card_price_color) price_el.style.color = attributes.card_price_color || '';
166 if (descr_el && attributes.card_descr_color) descr_el.style.color = attributes.card_descr_color;
167 current_el.backgroundColor = attributes.card_bg_color || '';
168 current_el.borderColor = attributes.card_border_color || '';
169 }
170 };
171
172
173 /**
174 * The edit function describes the structure of your block in the context of the
175 * editor. This represents what the editor will render when the block is used.
176 *
177 * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#edit
178 *
179 * @param {Object} props Properties passed to the function.
180 * @param {Object} props.attributes Available block attributes.
181 * @param {Function} props.setAttributes Function that updates individual attributes.
182 *
183 * @return {WPElement} Element to render.
184 */
185 export default function Edit({attributes, setAttributes}) {
186 const blockProps = useBlockProps();
187 useEffect(() => {
188 if (!attributes.id) {
189 setAttributes({ id: Math.random().toString(36).substr(2, 9) + '-' + Date.now() });
190 }
191 }, []);
192
193 const [activeTab, setActiveTab] = useState('settings');
194
195 const generateStyles = () => {
196 let styles = {}
197 if (attributes.is_inherit) return styles;
198
199 if (attributes.font_weight) styles.fontWeight = attributes.font_weight
200 if (attributes.button_font_size) styles.fontSize = attributes.button_font_size
201 if (attributes.text_transform) styles.textTransform = attributes.text_transform
202 if (attributes.font_family) styles.fontFamily = attributes.font_family
203 if (attributes.line_height) styles.lineHeight = attributes.line_height
204 if (attributes.letter_spacing) styles.letterSpacing = attributes.letter_spacing
205 if (attributes.button_border_radius) styles.borderRadius = attributes.button_border_radius
206 if (attributes.button_bg_color) styles.backgroundColor = attributes.button_bg_color;
207 if (attributes.button_text_color) styles.color = attributes.button_text_color;
208 if (attributes.border_color) styles.borderColor = attributes.border_color;
209 if (attributes.border_style && attributes.border_style !== 'default') styles.borderStyle = attributes.border_style;
210 if (attributes.border_width && attributes.border_style !== 'default') styles.borderWidth = attributes.border_width;
211 if (attributes.padding) styles.padding = attributes.padding;
212 return styles
213 }
214
215 const resourceCardStyles = () => {
216 let styles = {}
217
218 if (attributes.is_inherit) return styles;
219
220 if (attributes.card_padding) styles.padding = attributes.card_padding;
221 if (attributes.card_box_shadow) styles.boxShadow = attributes.card_box_shadow;
222 if (attributes.card_border_style && attributes.card_border_style !== 'default') styles.borderStyle = attributes.card_border_style;
223 if (attributes.card_border_radius) styles.borderRadius = attributes.card_border_radius;
224 if (attributes.card_border_width && attributes.card_border_style !== 'default') styles.borderWidth = attributes.card_border_width;
225 if (attributes.card_border_color) styles.borderColor = attributes.card_border_color;
226 if (attributes.card_bg_color) styles.backgroundColor = attributes.card_bg_color;
227 return styles
228 }
229
230 const cardPriceStyles = () => {
231 let styles = {}
232 if (attributes.is_inherit) return styles;
233
234 if (attributes.price_font_size) styles.fontSize = attributes.price_font_size
235 if ( attributes.card_price_color) styles.color = attributes.card_price_color
236
237 return styles;
238 }
239
240 const cardTitleStyles = () => {
241 let styles = {}
242 if (attributes.is_inherit) return styles;
243
244 if (attributes.title_font_size) styles.fontSize = attributes.title_font_size
245 if ( attributes.card_text_color) styles.color = attributes.card_text_color
246
247 return styles;
248 }
249
250 const cardDescrStyles = () => {
251 let styles = {}
252 if (attributes.is_inherit) return styles;
253
254 if (attributes.descr_font_size) styles.fontSize = attributes.descr_font_size
255 if ( attributes.card_descr_color) styles.color = attributes.card_descr_color
256
257 return styles;
258 }
259
260
261 const isIncludedInIds = (id, ids) => {
262 if (!ids) return true;
263 let clean_item_ids = ids.split(",").map(item => item.trim());
264 return clean_item_ids ? clean_item_ids.includes(id) : true;
265 }
266
267 const renderResources = () => {
268 let resources = []
269 switch (attributes.items) {
270 case 'services':
271 resources = latepoint_helper.services.filter((service) => isIncludedInIds(service.id, attributes.item_ids) && isIncludedInIds(service.category_id, attributes.group_ids))
272 break;
273 case 'agents':
274 resources = latepoint_helper.agents.filter((agent) => isIncludedInIds(agent.id, attributes.item_ids))
275 break;
276 case 'locations':
277 resources = latepoint_helper.locations.filter((location) => isIncludedInIds(location.id, attributes.item_ids) && isIncludedInIds(location.category_id, attributes.group_ids))
278 break;
279 case 'bundles':
280 resources = latepoint_helper.bundles.filter((bundle) => isIncludedInIds(bundle.id, attributes.item_ids))
281 break;
282 }
283 if (resources.length) {
284 if (attributes.limit) resources = resources.slice(0, attributes.limit)
285 let resources_items = resources.map((resource) =>
286 <Resource
287 key={resource.id}
288 style={resourceCardStyles()}
289 onMouseEnter={(e) => cardHoverColor(e, attributes, 'mouseEnter')}
290 onMouseLeave={(e) => cardHoverColor(e, attributes, 'mouseLeave')}
291 >
292 {(!attributes.hide_image && resource.image_url) && (
293 <ResourceImage>
294 <img src={resource.image_url} style={{ position: 'absolute', inset: 0, objectFit: 'cover', width: '100%', height: '100%' }}/>
295 </ResourceImage>
296 )}
297 <ResourceTitle className="lb-resource-title" style={cardTitleStyles()}>{resource.name}</ResourceTitle>
298 { (!attributes.hide_price && resource.price_formatted) && <ResourcePrice className="lb-resource-price" style={cardPriceStyles()}>{resource.price_formatted}</ResourcePrice>}
299 { (!attributes.hide_description && resource.description) && <ResourceDescription className="lb-resource-descr" style={cardDescrStyles()}>{resource.description}</ResourceDescription>}
300 <div className="wp-block-button">
301 <LatepointBookButton
302 style={generateStyles()}
303 onMouseEnter={(e) => btnHoverColor(e, attributes, 'mouseEnter')}
304 onMouseLeave={(e) => btnHoverColor(e, attributes, 'mouseLeave')}
305 className="latepoint-book-button wp-block-button__link">
306 {attributes.button_caption}
307 </LatepointBookButton>
308 </div>
309 </Resource>)
310 return <ListOfResources className={`resources-columns-${attributes.columns}`}>{resources_items}</ListOfResources>
311 } else {
312 return <NoMatches>{__('No Items Matching', 'latepoint')}</NoMatches>
313 }
314 }
315
316 const getGeneralTabs = () => {
317 let tabs = [
318 {name: 'settings', title: <div className="lb-tab-head"><SettingsIcon/>Settings</div>}
319 ];
320 if(!attributes.is_inherit){
321 tabs.push({name: 'styles', title: <div className="lb-tab-head"><StylesIcon/>Button</div>});
322 tabs.push({name: 'card_settings', title: <div className="lb-tab-head"><CardIcon/>Card</div>});
323 }
324 return tabs;
325 }
326
327 return (
328 <div {...blockProps}>
329 <InspectorControls>
330
331 <TabPanel
332 className="lb-general-tabs"
333 activeClass="active-tab"
334 tabs={getGeneralTabs()}
335 onSelect={(tabName) => setActiveTab(tabName)}
336 >
337 {(tab) => {
338 if (tab.name === 'settings') {
339 return (
340 <>
341 <Panel>
342 <PanelBody title="Button" initialOpen={true}>
343 <TextControl __nextHasNoMarginBottom __next40pxDefaultSize
344 label="Button Caption"
345 value={attributes.button_caption || ''}
346 onChange={(value) => setAttributes({button_caption: value})}
347 />
348 <ToggleControl __nextHasNoMarginBottom
349 label="Inherit From Theme"
350 checked={attributes.is_inherit}
351 onChange={(value) => setAttributes({is_inherit: value})}
352 />
353 </PanelBody>
354 </Panel>
355 <Panel>
356 <PanelBody title="Settings" initialOpen={false}>
357 <SelectControl __nextHasNoMarginBottom __next40pxDefaultSize
358 label={__('Resource Type', 'latepoint')}
359 onChange={(value) => setAttributes({items: value})}
360 value={attributes.items}
361 options={[
362 {value: 'services', label: __('Services', 'latepoint')},
363 {value: 'agents', label: __('Agents', 'latepoint')},
364 {value: 'locations', label: __('Locations', 'latepoint')},
365 {value: 'bundles', label: __('Bundles', 'latepoint')}]}
366 />
367 <SelectControl __nextHasNoMarginBottom __next40pxDefaultSize
368 label={__('Number of columns', 'latepoint')}
369 onChange={(value) => setAttributes({columns: value})}
370 value={attributes.columns ?? '4'}
371 options={[
372 {label: __('One', 'latepoint'), value: '1'},
373 {label: __('Two', 'latepoint'), value: '2'},
374 {label: __('Three', 'latepoint'), value: '3'},
375 {label: __('Four', 'latepoint'), value: '4'},
376 {label: __('Five', 'latepoint'), value: '5'}]}
377 />
378
379 {['services', 'bundles'].includes(attributes.items) && (
380 <>
381 {attributes.items === 'services' && (
382 <ToggleControl __nextHasNoMarginBottom
383 label="Hide Image"
384 checked={attributes.hide_image}
385 onChange={(value) => setAttributes({hide_image: value})}
386 />
387 )}
388 <ToggleControl __nextHasNoMarginBottom
389 label="Hide Price"
390 checked={attributes.hide_price}
391 onChange={(value) => setAttributes({hide_price: value})}
392 />
393 <ToggleControl __nextHasNoMarginBottom
394 label="Hide Description"
395 checked={attributes.hide_description}
396 onChange={(value) => setAttributes({hide_description: value})}
397 />
398 </>
399 )}
400 </PanelBody>
401 </Panel>
402 <Panel>
403 <PanelBody title="Booking Form Settings" initialOpen={false}>
404 <ToggleControl __nextHasNoMarginBottom
405 label="Hide Summary Panel"
406 checked={attributes.hide_summary}
407 onChange={(value) => setAttributes({hide_summary: value})}
408 />
409 <ToggleControl __nextHasNoMarginBottom
410 label="Hide Side Panel"
411 checked={attributes.hide_side_panel}
412 onChange={(value) => setAttributes({hide_side_panel: value})}
413 />
414 </PanelBody>
415 </Panel>
416 <Panel>
417 <PanelBody title="Step Settings" initialOpen={false}>
418 { attributes.items != 'agents' &&
419 <SelectControl __nextHasNoMarginBottom __next40pxDefaultSize
420 value={attributes.selected_agent}
421 label={__('Preselected Agent', 'latepoint')}
422 onChange={(value) => setAttributes({selected_agent: value})}
423 options={latepoint_helper.selected_agents_options}
424 />
425 }
426 { !['services', 'bundles'].includes(attributes.items) &&
427 <SelectControl __nextHasNoMarginBottom __next40pxDefaultSize
428 value={attributes.selected_service}
429 label={__('Preselected Service', 'latepoint')}
430 onChange={(value) => setAttributes({selected_service: value})}
431 options={latepoint_helper.selected_services_options}
432 />
433 }
434 { !['services', 'bundles'].includes(attributes.items) &&
435 <SelectControl __nextHasNoMarginBottom __next40pxDefaultSize
436 value={attributes.selected_service_category}
437 label={__('Preselected Service Category', 'latepoint')}
438 onChange={(value) => setAttributes({selected_service_category: value})}
439 options={latepoint_helper.selected_service_categories_options}
440 />
441 }
442 { !['services', 'bundles'].includes(attributes.items) &&
443 <SelectControl __nextHasNoMarginBottom __next40pxDefaultSize
444 value={attributes.selected_bundle}
445 label={__('Preselected Bundle', 'latepoint')}
446 onChange={(value) => setAttributes({selected_bundle: value})}
447 options={latepoint_helper.selected_bundles_options}
448 />
449 }
450 {attributes.items != 'locations' &&
451 <SelectControl __nextHasNoMarginBottom __next40pxDefaultSize
452 value={attributes.selected_location}
453 label={__('Preselected Location', 'latepoint')}
454 onChange={(value) => setAttributes({selected_location: value})}
455 options={latepoint_helper.selected_locations_options}
456 />
457 }
458
459 <TextControl __nextHasNoMarginBottom __next40pxDefaultSize
460 label={__('Preselected Booking Start Date', 'latepoint')}
461 value={attributes.selected_start_date || ''}
462 placeholder="YYYY-MM-DD"
463 onChange={(value) => setAttributes({selected_start_date: value})}
464 />
465
466 <TextControl __nextHasNoMarginBottom __next40pxDefaultSize
467 label={__('Preselected Booking Start Time', 'latepoint')}
468 value={attributes.selected_start_time || ''}
469 placeholder="Minutes"
470 onChange={(value) => setAttributes({selected_start_time: value})}
471 />
472
473 <TextControl __nextHasNoMarginBottom __next40pxDefaultSize
474 label={__('Preselected Duration', 'latepoint')}
475 value={attributes.selected_duration || ''}
476 placeholder="Minutes"
477 onChange={(value) => setAttributes({selected_duration: value})}
478 />
479
480 <TextControl __nextHasNoMarginBottom __next40pxDefaultSize
481 label={__('Preselected Total Attendees', 'latepoint')}
482 value={attributes.selected_total_attendees || ''}
483 placeholder="Number"
484 onChange={(value) => setAttributes({selected_total_attendees: value})}
485 />
486 </PanelBody>
487 </Panel>
488 <Panel>
489 <PanelBody title="Items Settings" initialOpen={false}>
490 <TextControl __nextHasNoMarginBottom __next40pxDefaultSize
491 label="Max Number of Items Shown"
492 value={attributes.limit || ''}
493 onChange={(value) => setAttributes({limit: value})}
494 />
495 <TextControl __nextHasNoMarginBottom __next40pxDefaultSize
496 label="Show Selected Items"
497 placeholder="Comma separated item IDs"
498 value={attributes.item_ids || ''}
499 onChange={(value) => setAttributes({item_ids: value})}
500 />
501
502 {attributes.items != 'bundles' &&
503 <TextControl __nextHasNoMarginBottom __next40pxDefaultSize
504 label="Show Selected Categories"
505 placeholder="Comma separated category IDs"
506 value={attributes.group_ids || ''}
507 onChange={(value) => setAttributes({group_ids: value})}
508 />
509 }
510 </PanelBody>
511 </Panel>
512 <Panel>
513 <PanelBody title="Other Settings" initialOpen={false}>
514 <TextControl __nextHasNoMarginBottom __next40pxDefaultSize
515 label="Source ID"
516 value={attributes.source_id || ''}
517 onChange={(value) => setAttributes({source_id: value})}
518 />
519 <TextControl __nextHasNoMarginBottom __next40pxDefaultSize
520 label="Calendar Start Date"
521 value={attributes.calendar_start_date || ''}
522 placeholder="YYYY-MM-DD"
523 onChange={(value) => setAttributes({calendar_start_date: value})}
524 />
525 {!['services', 'bundles'].includes(attributes.items) &&
526 <TextControl __nextHasNoMarginBottom __next40pxDefaultSize
527 label="Show Services"
528 placeholder="Comma separated service IDs"
529 value={attributes.show_services || ''}
530 onChange={(value) => setAttributes({show_services: value})}
531 />
532 }
533 {!['services', 'bundles'].includes(attributes.items) &&
534 <TextControl __nextHasNoMarginBottom __next40pxDefaultSize
535 label="Show Service Categories"
536 placeholder="Comma separated category IDs"
537 value={attributes.show_service_categories || ''}
538 onChange={(value) => setAttributes({show_service_categories: value})}
539 />
540 }
541 {attributes.items != 'agents' &&
542 <TextControl __nextHasNoMarginBottom __next40pxDefaultSize
543 label="Show Agents"
544 placeholder="Comma separated agent IDs"
545 value={attributes.show_agents || ''}
546 onChange={(value) => setAttributes({show_agents: value})}
547 />
548 }
549 {attributes.items != 'locations' &&
550 <TextControl __nextHasNoMarginBottom __next40pxDefaultSize
551 label="Show Locations"
552 placeholder="Comma separated location IDs"
553 value={attributes.show_locations || ''}
554 onChange={(value) => setAttributes({show_locations: value})}
555 />
556 }
557 </PanelBody>
558 </Panel>
559 </>
560 );
561 }
562 if (tab.name === 'styles') {
563 return (
564 <>
565 {!attributes.is_inherit && (
566 <Panel>
567 <PanelBody>
568 <PaddingBoxControl
569 label={__('Padding', 'latepoint')}
570 paddingAttribute="padding"
571 attributes={attributes}
572 setAttributes={setAttributes}
573 />
574 </PanelBody>
575 <PanelBody title="Color" initialOpen={false}>
576 <TabPanel
577 className="lb-tabs"
578 activeClass="active-tab"
579 tabs={[
580 {name: 'tab-normal', title: 'Normal',},
581 {name: 'tab-hover', title: 'Hover',},
582 ]}
583 >
584 {(tab) => {
585 if (tab.name === 'tab-normal') {
586 return (
587 <>
588 <PanelRow>
589 <ColorSelectorControl
590 attributes={attributes}
591 setAttributes={setAttributes}
592 colorAttribute="button_bg_color"
593 label={__('Background Color', 'latepoint')}
594 ></ColorSelectorControl>
595 </PanelRow>
596 <PanelRow>
597 <ColorSelectorControl
598 attributes={attributes}
599 setAttributes={setAttributes}
600 colorAttribute="button_text_color"
601 label={__('Text Color', 'latepoint')}
602 ></ColorSelectorControl>
603 </PanelRow>
604 </>
605 );
606 }
607 if (tab.name === 'tab-hover') {
608 return (
609 <>
610 <PanelRow>
611 <ColorSelectorControl
612 attributes={attributes}
613 setAttributes={setAttributes}
614 colorAttribute="bg_color_hover"
615 label={__('Background Color', 'latepoint')}
616 ></ColorSelectorControl>
617 </PanelRow>
618 <PanelRow>
619 <ColorSelectorControl
620 attributes={attributes}
621 setAttributes={setAttributes}
622 colorAttribute="text_color_hover"
623 label={__('Text Color', 'latepoint')}
624 ></ColorSelectorControl>
625 </PanelRow>
626 </>
627 );
628 }
629 }}
630 </TabPanel>
631 </PanelBody>
632 <PanelBody title="Text" initialOpen={false}>
633 <TypographyControl attributes={attributes} setAttributes={setAttributes} fontSizeAttr="button_font_size"></TypographyControl>
634 </PanelBody>
635 <PanelBody title="Border" initialOpen={false}>
636 <BorderControl attributes={attributes} setAttributes={setAttributes} borderRadiusAttr="button_border_radius"></BorderControl>
637 </PanelBody>
638 </Panel>
639 )}
640 </>
641 );
642 }
643 if (tab.name === 'card_settings') {
644 return (
645 <>
646 <Panel>
647 <PanelBody title="Color" initialOpen={false}>
648 <TabPanel
649 className="lb-tabs"
650 activeClass="active-tab"
651 tabs={[
652 {name: 'tab-normal', title: 'Normal',},
653 {name: 'tab-hover', title: 'Hover',},
654 ]}
655 >
656 {(tab) => {
657 if (tab.name === 'tab-normal') {
658 return (
659 <>
660 <PanelRow>
661 <ColorSelectorControl
662 attributes={attributes}
663 setAttributes={setAttributes}
664 colorAttribute="card_bg_color"
665 label={__('Background Color', 'latepoint')}
666 ></ColorSelectorControl>
667 </PanelRow>
668 <PanelRow>
669 <ColorSelectorControl
670 attributes={attributes}
671 setAttributes={setAttributes}
672 colorAttribute="card_text_color"
673 label={__('Title Color', 'latepoint')}
674 ></ColorSelectorControl>
675 </PanelRow>
676 {(['services', 'bundles'].includes(attributes.items) && !attributes.hide_price) && (
677 <PanelRow>
678 <ColorSelectorControl
679 attributes={attributes}
680 setAttributes={setAttributes}
681 colorAttribute="card_price_color"
682 label={__('Price Color', 'latepoint')}
683 ></ColorSelectorControl>
684 </PanelRow>
685 )}
686 {(['services', 'bundles'].includes(attributes.items) && !attributes.hide_description) && (
687 <PanelRow>
688 <ColorSelectorControl
689 attributes={attributes}
690 setAttributes={setAttributes}
691 colorAttribute="card_descr_color"
692 label={__('Description Color', 'latepoint')}
693 ></ColorSelectorControl>
694 </PanelRow>
695 )}
696 </>
697 );
698 }
699 if (tab.name === 'tab-hover') {
700 return (
701 <>
702 <PanelRow>
703 <ColorSelectorControl
704 attributes={attributes}
705 setAttributes={setAttributes}
706 colorAttribute="card_bg_color_hover"
707 label={__('Background Color', 'latepoint')}
708 ></ColorSelectorControl>
709 </PanelRow>
710 <PanelRow>
711 <ColorSelectorControl
712 attributes={attributes}
713 setAttributes={setAttributes}
714 colorAttribute="card_text_color_hover"
715 label={__('Title Color', 'latepoint')}
716 ></ColorSelectorControl>
717 </PanelRow>
718 {(['services', 'bundles'].includes(attributes.items) && !attributes.hide_price) && (
719 <PanelRow>
720 <ColorSelectorControl
721 attributes={attributes}
722 setAttributes={setAttributes}
723 colorAttribute="card_price_color_hover"
724 label={__('Price Color', 'latepoint')}
725 ></ColorSelectorControl>
726 </PanelRow>
727 )}
728 {(['services', 'bundles'].includes(attributes.items) && !attributes.hide_description) && (
729 <PanelRow>
730 <ColorSelectorControl
731 attributes={attributes}
732 setAttributes={setAttributes}
733 colorAttribute="card_descr_color_hover"
734 label={__('Description Color', 'latepoint')}
735 ></ColorSelectorControl>
736 </PanelRow>
737 )}
738 </>
739 );
740 }
741 }}
742 </TabPanel>
743 </PanelBody>
744
745 <PanelBody title="Title" initialOpen={false}>
746 <FontSizeControl attributes={attributes} setAttributes={setAttributes} fontSizeAttr="title_font_size"></FontSizeControl>
747 </PanelBody>
748
749 {(['services', 'bundles'].includes(attributes.items) && !attributes.hide_price) && (
750 <PanelBody title="Price" initialOpen={false}>
751 <FontSizeControl attributes={attributes} setAttributes={setAttributes} fontSizeAttr="price_font_size"></FontSizeControl>
752 </PanelBody>
753 )}
754
755 {(['services', 'bundles'].includes(attributes.items) && !attributes.hide_description) && (
756 <PanelBody title="Description" initialOpen={false}>
757 <FontSizeControl attributes={attributes} setAttributes={setAttributes} fontSizeAttr="descr_font_size"></FontSizeControl>
758 </PanelBody>
759 )}
760
761
762 <PanelBody title="Box Shadow" initialOpen={false}>
763 <BoxShadowControl
764 shadowAttribute="card_box_shadow"
765 attributes={attributes}
766 setAttributes={setAttributes}
767 />
768 </PanelBody>
769 <PanelBody title="Border" initialOpen={false}>
770 <UnitControl
771 label={__('Border Radius')}
772 className="latepoint-control-two-columns"
773 onChange={(border_radius) => setAttributes({card_border_radius: border_radius})}
774 units={[
775 {value: 'px', label: 'px', default: 0},
776 {value: '%', label: '%', default: 10},
777 {value: 'em', label: 'em', default: 0},
778 ]}
779 value={attributes.card_border_radius}
780 />
781
782 <SelectControl __nextHasNoMarginBottom __next40pxDefaultSize
783 label={__('Style', 'latepoint')}
784 value={attributes.card_border_style}
785 className="latepoint-control-two-columns"
786 options={[
787 {label: __('Default', 'latepoint'), value: 'default'},
788 {label: __('None', 'latepoint'), value: 'none'},
789 {label: __('Solid', 'latepoint'), value: 'solid'},
790 {label: __('Dotted', 'latepoint'), value: 'dotted'},
791 {label: __('Dashed', 'latepoint'), value: 'dashed'},
792 ]}
793 onChange={(border_style) => setAttributes({card_border_style: border_style})}
794 />
795
796 {attributes.card_border_style !== 'default' && attributes.card_border_style !== 'none' && (
797 <>
798 <UnitControl
799 label={__('Border Width')}
800 className="latepoint-control-two-columns"
801 onChange={(value) => {
802 setAttributes({card_border_width: value})
803 }}
804 units={[
805 {value: 'px', label: 'px', default: 0},
806 {value: '%', label: '%', default: 10},
807 {value: 'em', label: 'em', default: 0},
808 ]}
809 value={attributes.card_border_width}
810 />
811 <TabPanel
812 className="lb-tabs"
813 activeClass="active-tab"
814 tabs={[
815 {name: 'tab-normal', title: 'Normal',},
816 {name: 'tab-hover', title: 'Hover',},
817 ]}
818 >
819 {(tab) => {
820 if (tab.name === 'tab-normal') {
821 return (
822 <>
823 <ColorSelectorControl
824 attributes={attributes}
825 setAttributes={setAttributes}
826 colorAttribute="card_border_color"
827 label={__('Border Color', 'latepoint')}
828 ></ColorSelectorControl>
829 </>
830 );
831 }
832 if (tab.name === 'tab-hover') {
833 return (
834 <>
835 <ColorSelectorControl
836 attributes={attributes}
837 setAttributes={setAttributes}
838 colorAttribute="card_border_color_hover"
839 label={__('Border Color', 'latepoint')}
840 ></ColorSelectorControl>
841 </>
842 );
843 }
844 }}
845 </TabPanel>
846 </>
847 )}
848 </PanelBody>
849 <PanelBody title="Spacing" initialOpen={false}>
850 <PaddingBoxControl
851 label={__('Card Padding', 'latepoint')}
852 paddingAttribute="card_padding" attributes={attributes}
853 setAttributes={setAttributes}></PaddingBoxControl>
854 </PanelBody>
855 </Panel>
856 </>
857 );
858 }
859 }}
860 </TabPanel>
861 <Panel>
862 <Separator></Separator>
863 </Panel>
864 </InspectorControls>
865
866 <IframeEmotionCacheProvider>
867 <ListOfResourcesWrapper>
868 {renderResources()}
869 </ListOfResourcesWrapper>
870 </IframeEmotionCacheProvider>
871 </div>
872 );
873 }
874