All checks were successful
Create Release Package / build-release (push) Successful in 1m20s
- Room search with availability, capacity, room type, amenity, price range, and building filters - AJAX-powered search with pagination and load more - Shortcodes: [bnb_buildings], [bnb_rooms], [bnb_room_search], [bnb_building], [bnb_room] - Widgets: Similar Rooms, Building Rooms, Availability Calendar - Gutenberg blocks: Building, Room, Room Search, Buildings List, Rooms List - Frontend CSS with responsive design and CSS custom properties - Frontend JavaScript with SearchForm, CalendarWidget, AvailabilityForm, PriceCalculator Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
490 lines
14 KiB
JavaScript
490 lines
14 KiB
JavaScript
/**
|
|
* WP BnB Gutenberg Blocks
|
|
*
|
|
* @package Magdev\WpBnb
|
|
*/
|
|
|
|
(function(wp) {
|
|
'use strict';
|
|
|
|
const { registerBlockType } = wp.blocks;
|
|
const { createElement, Fragment } = wp.element;
|
|
const { InspectorControls, useBlockProps } = wp.blockEditor;
|
|
const { PanelBody, SelectControl, ToggleControl, RangeControl, Placeholder, Spinner } = wp.components;
|
|
const { ServerSideRender } = wp.editor || wp.serverSideRender;
|
|
const { __ } = wp.i18n;
|
|
const el = createElement;
|
|
|
|
// Get localized data
|
|
const { buildings, rooms, roomTypes, i18n } = wpBnbBlocks;
|
|
|
|
// Building options for select
|
|
const buildingOptions = [
|
|
{ value: 0, label: i18n.selectBuilding },
|
|
...buildings
|
|
];
|
|
|
|
// Room options for select
|
|
const roomOptions = [
|
|
{ value: 0, label: i18n.selectRoom },
|
|
...rooms.map(r => ({
|
|
value: r.value,
|
|
label: r.building ? `${r.label} (${r.building})` : r.label
|
|
}))
|
|
];
|
|
|
|
// Room type options
|
|
const roomTypeOptions = [
|
|
{ value: '', label: i18n.allTypes },
|
|
...roomTypes.map(t => ({
|
|
value: t.slug,
|
|
label: t.name
|
|
}))
|
|
];
|
|
|
|
// Building filter options for rooms block
|
|
const buildingFilterOptions = [
|
|
{ value: 0, label: i18n.allBuildings },
|
|
...buildings
|
|
];
|
|
|
|
/**
|
|
* Building Block
|
|
*/
|
|
registerBlockType('wp-bnb/building', {
|
|
title: i18n.buildingBlock,
|
|
icon: 'building',
|
|
category: 'widgets',
|
|
attributes: {
|
|
buildingId: { type: 'number', default: 0 },
|
|
showImage: { type: 'boolean', default: true },
|
|
showAddress: { type: 'boolean', default: true },
|
|
showRooms: { type: 'boolean', default: true },
|
|
showContact: { type: 'boolean', default: true }
|
|
},
|
|
|
|
edit: function(props) {
|
|
const { attributes, setAttributes } = props;
|
|
const blockProps = useBlockProps();
|
|
|
|
return el(Fragment, {},
|
|
el(InspectorControls, {},
|
|
el(PanelBody, { title: i18n.displaySettings },
|
|
el(SelectControl, {
|
|
label: i18n.buildingBlock,
|
|
value: attributes.buildingId,
|
|
options: buildingOptions,
|
|
onChange: (value) => setAttributes({ buildingId: parseInt(value, 10) })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showImage,
|
|
checked: attributes.showImage,
|
|
onChange: (value) => setAttributes({ showImage: value })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showAddress,
|
|
checked: attributes.showAddress,
|
|
onChange: (value) => setAttributes({ showAddress: value })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showRooms,
|
|
checked: attributes.showRooms,
|
|
onChange: (value) => setAttributes({ showRooms: value })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showContact,
|
|
checked: attributes.showContact,
|
|
onChange: (value) => setAttributes({ showContact: value })
|
|
})
|
|
)
|
|
),
|
|
el('div', blockProps,
|
|
attributes.buildingId ?
|
|
el(ServerSideRender, {
|
|
block: 'wp-bnb/building',
|
|
attributes: attributes,
|
|
LoadingResponsePlaceholder: () => el(Placeholder, { icon: 'building', label: i18n.buildingBlock }, el(Spinner))
|
|
}) :
|
|
el(Placeholder, { icon: 'building', label: i18n.buildingBlock },
|
|
buildings.length === 0 ?
|
|
el('p', {}, i18n.noBuildings) :
|
|
el(SelectControl, {
|
|
value: attributes.buildingId,
|
|
options: buildingOptions,
|
|
onChange: (value) => setAttributes({ buildingId: parseInt(value, 10) })
|
|
})
|
|
)
|
|
)
|
|
);
|
|
},
|
|
|
|
save: function() {
|
|
return null; // Server-side rendered
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Room Block
|
|
*/
|
|
registerBlockType('wp-bnb/room', {
|
|
title: i18n.roomBlock,
|
|
icon: 'admin-home',
|
|
category: 'widgets',
|
|
attributes: {
|
|
roomId: { type: 'number', default: 0 },
|
|
showImage: { type: 'boolean', default: true },
|
|
showGallery: { type: 'boolean', default: true },
|
|
showPrice: { type: 'boolean', default: true },
|
|
showAmenities: { type: 'boolean', default: true },
|
|
showAvailability: { type: 'boolean', default: true }
|
|
},
|
|
|
|
edit: function(props) {
|
|
const { attributes, setAttributes } = props;
|
|
const blockProps = useBlockProps();
|
|
|
|
return el(Fragment, {},
|
|
el(InspectorControls, {},
|
|
el(PanelBody, { title: i18n.displaySettings },
|
|
el(SelectControl, {
|
|
label: i18n.roomBlock,
|
|
value: attributes.roomId,
|
|
options: roomOptions,
|
|
onChange: (value) => setAttributes({ roomId: parseInt(value, 10) })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showImage,
|
|
checked: attributes.showImage,
|
|
onChange: (value) => setAttributes({ showImage: value })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showGallery,
|
|
checked: attributes.showGallery,
|
|
onChange: (value) => setAttributes({ showGallery: value })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showPrice,
|
|
checked: attributes.showPrice,
|
|
onChange: (value) => setAttributes({ showPrice: value })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showAmenities,
|
|
checked: attributes.showAmenities,
|
|
onChange: (value) => setAttributes({ showAmenities: value })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showAvailability,
|
|
checked: attributes.showAvailability,
|
|
onChange: (value) => setAttributes({ showAvailability: value })
|
|
})
|
|
)
|
|
),
|
|
el('div', blockProps,
|
|
attributes.roomId ?
|
|
el(ServerSideRender, {
|
|
block: 'wp-bnb/room',
|
|
attributes: attributes,
|
|
LoadingResponsePlaceholder: () => el(Placeholder, { icon: 'admin-home', label: i18n.roomBlock }, el(Spinner))
|
|
}) :
|
|
el(Placeholder, { icon: 'admin-home', label: i18n.roomBlock },
|
|
rooms.length === 0 ?
|
|
el('p', {}, i18n.noRooms) :
|
|
el(SelectControl, {
|
|
value: attributes.roomId,
|
|
options: roomOptions,
|
|
onChange: (value) => setAttributes({ roomId: parseInt(value, 10) })
|
|
})
|
|
)
|
|
)
|
|
);
|
|
},
|
|
|
|
save: function() {
|
|
return null;
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Room Search Block
|
|
*/
|
|
registerBlockType('wp-bnb/room-search', {
|
|
title: i18n.roomSearchBlock,
|
|
icon: 'search',
|
|
category: 'widgets',
|
|
attributes: {
|
|
layout: { type: 'string', default: 'grid' },
|
|
columns: { type: 'number', default: 3 },
|
|
showDates: { type: 'boolean', default: true },
|
|
showGuests: { type: 'boolean', default: true },
|
|
showRoomType: { type: 'boolean', default: true },
|
|
showAmenities: { type: 'boolean', default: true },
|
|
showPriceRange: { type: 'boolean', default: true },
|
|
showBuilding: { type: 'boolean', default: true },
|
|
resultsPerPage: { type: 'number', default: 12 }
|
|
},
|
|
|
|
edit: function(props) {
|
|
const { attributes, setAttributes } = props;
|
|
const blockProps = useBlockProps();
|
|
|
|
return el(Fragment, {},
|
|
el(InspectorControls, {},
|
|
el(PanelBody, { title: i18n.displaySettings },
|
|
el(SelectControl, {
|
|
label: i18n.layout,
|
|
value: attributes.layout,
|
|
options: [
|
|
{ value: 'grid', label: i18n.grid },
|
|
{ value: 'list', label: i18n.list }
|
|
],
|
|
onChange: (value) => setAttributes({ layout: value })
|
|
}),
|
|
el(RangeControl, {
|
|
label: i18n.columns,
|
|
value: attributes.columns,
|
|
onChange: (value) => setAttributes({ columns: value }),
|
|
min: 1,
|
|
max: 4
|
|
}),
|
|
el(RangeControl, {
|
|
label: i18n.resultsPerPage,
|
|
value: attributes.resultsPerPage,
|
|
onChange: (value) => setAttributes({ resultsPerPage: value }),
|
|
min: 4,
|
|
max: 48
|
|
})
|
|
),
|
|
el(PanelBody, { title: i18n.filterSettings, initialOpen: false },
|
|
el(ToggleControl, {
|
|
label: i18n.showDates,
|
|
checked: attributes.showDates,
|
|
onChange: (value) => setAttributes({ showDates: value })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showGuests,
|
|
checked: attributes.showGuests,
|
|
onChange: (value) => setAttributes({ showGuests: value })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showRoomType,
|
|
checked: attributes.showRoomType,
|
|
onChange: (value) => setAttributes({ showRoomType: value })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showAmenities,
|
|
checked: attributes.showAmenities,
|
|
onChange: (value) => setAttributes({ showAmenities: value })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showPriceRange,
|
|
checked: attributes.showPriceRange,
|
|
onChange: (value) => setAttributes({ showPriceRange: value })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showBuilding,
|
|
checked: attributes.showBuilding,
|
|
onChange: (value) => setAttributes({ showBuilding: value })
|
|
})
|
|
)
|
|
),
|
|
el('div', blockProps,
|
|
el(ServerSideRender, {
|
|
block: 'wp-bnb/room-search',
|
|
attributes: attributes,
|
|
LoadingResponsePlaceholder: () => el(Placeholder, { icon: 'search', label: i18n.roomSearchBlock }, el(Spinner))
|
|
})
|
|
)
|
|
);
|
|
},
|
|
|
|
save: function() {
|
|
return null;
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Buildings List Block
|
|
*/
|
|
registerBlockType('wp-bnb/buildings', {
|
|
title: i18n.buildingsBlock,
|
|
icon: 'building',
|
|
category: 'widgets',
|
|
attributes: {
|
|
layout: { type: 'string', default: 'grid' },
|
|
columns: { type: 'number', default: 3 },
|
|
limit: { type: 'number', default: -1 },
|
|
showImage: { type: 'boolean', default: true },
|
|
showAddress: { type: 'boolean', default: true },
|
|
showRoomsCount: { type: 'boolean', default: true }
|
|
},
|
|
|
|
edit: function(props) {
|
|
const { attributes, setAttributes } = props;
|
|
const blockProps = useBlockProps();
|
|
|
|
return el(Fragment, {},
|
|
el(InspectorControls, {},
|
|
el(PanelBody, { title: i18n.displaySettings },
|
|
el(SelectControl, {
|
|
label: i18n.layout,
|
|
value: attributes.layout,
|
|
options: [
|
|
{ value: 'grid', label: i18n.grid },
|
|
{ value: 'list', label: i18n.list }
|
|
],
|
|
onChange: (value) => setAttributes({ layout: value })
|
|
}),
|
|
el(RangeControl, {
|
|
label: i18n.columns,
|
|
value: attributes.columns,
|
|
onChange: (value) => setAttributes({ columns: value }),
|
|
min: 1,
|
|
max: 4
|
|
}),
|
|
el(RangeControl, {
|
|
label: i18n.limit,
|
|
value: attributes.limit,
|
|
onChange: (value) => setAttributes({ limit: value }),
|
|
min: -1,
|
|
max: 20
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showImage,
|
|
checked: attributes.showImage,
|
|
onChange: (value) => setAttributes({ showImage: value })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showAddress,
|
|
checked: attributes.showAddress,
|
|
onChange: (value) => setAttributes({ showAddress: value })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showRoomsCount,
|
|
checked: attributes.showRoomsCount,
|
|
onChange: (value) => setAttributes({ showRoomsCount: value })
|
|
})
|
|
)
|
|
),
|
|
el('div', blockProps,
|
|
el(ServerSideRender, {
|
|
block: 'wp-bnb/buildings',
|
|
attributes: attributes,
|
|
LoadingResponsePlaceholder: () => el(Placeholder, { icon: 'building', label: i18n.buildingsBlock }, el(Spinner))
|
|
})
|
|
)
|
|
);
|
|
},
|
|
|
|
save: function() {
|
|
return null;
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Rooms List Block
|
|
*/
|
|
registerBlockType('wp-bnb/rooms', {
|
|
title: i18n.roomsBlock,
|
|
icon: 'admin-home',
|
|
category: 'widgets',
|
|
attributes: {
|
|
layout: { type: 'string', default: 'grid' },
|
|
columns: { type: 'number', default: 3 },
|
|
limit: { type: 'number', default: 12 },
|
|
buildingId: { type: 'number', default: 0 },
|
|
roomType: { type: 'string', default: '' },
|
|
showImage: { type: 'boolean', default: true },
|
|
showPrice: { type: 'boolean', default: true },
|
|
showCapacity: { type: 'boolean', default: true },
|
|
showAmenities: { type: 'boolean', default: true },
|
|
showBuilding: { type: 'boolean', default: true }
|
|
},
|
|
|
|
edit: function(props) {
|
|
const { attributes, setAttributes } = props;
|
|
const blockProps = useBlockProps();
|
|
|
|
return el(Fragment, {},
|
|
el(InspectorControls, {},
|
|
el(PanelBody, { title: i18n.displaySettings },
|
|
el(SelectControl, {
|
|
label: i18n.layout,
|
|
value: attributes.layout,
|
|
options: [
|
|
{ value: 'grid', label: i18n.grid },
|
|
{ value: 'list', label: i18n.list }
|
|
],
|
|
onChange: (value) => setAttributes({ layout: value })
|
|
}),
|
|
el(RangeControl, {
|
|
label: i18n.columns,
|
|
value: attributes.columns,
|
|
onChange: (value) => setAttributes({ columns: value }),
|
|
min: 1,
|
|
max: 4
|
|
}),
|
|
el(RangeControl, {
|
|
label: i18n.limit,
|
|
value: attributes.limit,
|
|
onChange: (value) => setAttributes({ limit: value }),
|
|
min: 1,
|
|
max: 48
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showImage,
|
|
checked: attributes.showImage,
|
|
onChange: (value) => setAttributes({ showImage: value })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showPrice,
|
|
checked: attributes.showPrice,
|
|
onChange: (value) => setAttributes({ showPrice: value })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showCapacity,
|
|
checked: attributes.showCapacity,
|
|
onChange: (value) => setAttributes({ showCapacity: value })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showAmenities,
|
|
checked: attributes.showAmenities,
|
|
onChange: (value) => setAttributes({ showAmenities: value })
|
|
}),
|
|
el(ToggleControl, {
|
|
label: i18n.showBuilding,
|
|
checked: attributes.showBuilding,
|
|
onChange: (value) => setAttributes({ showBuilding: value })
|
|
})
|
|
),
|
|
el(PanelBody, { title: i18n.filterSettings, initialOpen: false },
|
|
el(SelectControl, {
|
|
label: i18n.buildingBlock,
|
|
value: attributes.buildingId,
|
|
options: buildingFilterOptions,
|
|
onChange: (value) => setAttributes({ buildingId: parseInt(value, 10) })
|
|
}),
|
|
el(SelectControl, {
|
|
label: i18n.roomType,
|
|
value: attributes.roomType,
|
|
options: roomTypeOptions,
|
|
onChange: (value) => setAttributes({ roomType: value })
|
|
})
|
|
)
|
|
),
|
|
el('div', blockProps,
|
|
el(ServerSideRender, {
|
|
block: 'wp-bnb/rooms',
|
|
attributes: attributes,
|
|
LoadingResponsePlaceholder: () => el(Placeholder, { icon: 'admin-home', label: i18n.roomsBlock }, el(Spinner))
|
|
})
|
|
)
|
|
);
|
|
},
|
|
|
|
save: function() {
|
|
return null;
|
|
}
|
|
});
|
|
|
|
})(window.wp);
|