| @@ -6,9 +6,12 @@ | ||
| 6 | 6 | SelectControl, |
| 7 | 7 | ToggleControl, |
| 8 | 8 | } from "@wordpress/components"; |
| 9 | 9 | import { __ } from "@wordpress/i18n"; |
| 10 | +import { useEffect, useRef } from "@wordpress/element"; | |
| 10 | 11 | import ServerSideRender from "@wordpress/server-side-render"; |
| 12 | +import { ClassificationMultiSelect } from "../components/ClassificationMultiSelect"; | |
| 13 | +import { migrateNumericCsvPairToIds } from "../utils/migrateTaxonomyIds"; | |
| 11 | 14 | |
| 12 | 15 | interface DestinationBlockAttributes { |
| 13 | 16 | order: "asc" | "desc"; |
| 14 | 17 | columns: number; |
| @@ -14,8 +17,16 @@ | ||
| 14 | 17 | columns: number; |
| 15 | 18 | per_page: number; |
| 16 | 19 | title: string; |
| 17 | 20 | show_pagination: boolean; |
| 21 | + destinationIds: number[]; | |
| 22 | + destination_ids?: string; | |
| 23 | + destination?: string; | |
| 24 | + show_trip_count: boolean; | |
| 25 | + show_description: boolean; | |
| 26 | + show_image: boolean; | |
| 27 | + hide_empty: boolean; | |
| 28 | + featured_only: boolean; | |
| 18 | 29 | } |
| 19 | 30 | |
| 20 | 31 | interface EditProps { |
| 21 | 32 | attributes: DestinationBlockAttributes; |
| @@ -21,9 +32,43 @@ | ||
| 21 | 32 | attributes: DestinationBlockAttributes; |
| 22 | 33 | setAttributes: (attrs: Partial<DestinationBlockAttributes>) => void; |
| 23 | 34 | } |
| 24 | 35 | |
| 36 | +function normalizeIds(arr: number[] | undefined): number[] { | |
| 37 | + return Array.isArray(arr) | |
| 38 | + ? [...new Set(arr.map((n) => parseInt(String(n), 10)).filter((n) => n > 0))] | |
| 39 | + : []; | |
| 40 | +} | |
| 41 | + | |
| 25 | 42 | export default function Edit({ attributes, setAttributes }: EditProps) { |
| 43 | + const migratedOnce = useRef(false); | |
| 44 | + | |
| 45 | + useEffect(() => { | |
| 46 | + if (migratedOnce.current) { | |
| 47 | + return; | |
| 48 | + } | |
| 49 | + migratedOnce.current = true; | |
| 50 | + | |
| 51 | + let ids = normalizeIds(attributes.destinationIds); | |
| 52 | + if (ids.length === 0) { | |
| 53 | + ids = migrateNumericCsvPairToIds( | |
| 54 | + attributes.destination_ids, | |
| 55 | + attributes.destination, | |
| 56 | + ); | |
| 57 | + } | |
| 58 | + if (ids.length === 0) { | |
| 59 | + return; | |
| 60 | + } | |
| 61 | + setAttributes({ | |
| 62 | + destinationIds: ids, | |
| 63 | + destination: "", | |
| 64 | + destination_ids: "", | |
| 65 | + }); | |
| 66 | + // eslint-disable-next-line react-hooks/exhaustive-deps | |
| 67 | + }, [setAttributes]); | |
| 68 | + | |
| 69 | + const destinationIds = normalizeIds(attributes.destinationIds); | |
| 70 | + | |
| 26 | 71 | return ( |
| 27 | 72 | <> |
| 28 | 73 | <InspectorControls> |
| 29 | 74 | <PanelBody |
| @@ -72,8 +117,60 @@ | ||
| 72 | 117 | label={__("Show pagination", "yatra")} |
| 73 | 118 | checked={attributes.show_pagination} |
| 74 | 119 | onChange={(value: boolean) => |
| 75 | 120 | setAttributes({ show_pagination: value }) |
| 121 | + } | |
| 122 | + /> | |
| 123 | + <ClassificationMultiSelect | |
| 124 | + taxonomy="destination" | |
| 125 | + label={__("Destinations to show", "yatra")} | |
| 126 | + help={__( | |
| 127 | + 'Pick "All published" for the full catalog; otherwise search and tick specific destinations.', | |
| 128 | + "yatra", | |
| 129 | + )} | |
| 130 | + value={destinationIds} | |
| 131 | + onChange={(ids) => setAttributes({ destinationIds: ids })} | |
| 132 | + /> | |
| 133 | + </PanelBody> | |
| 134 | + | |
| 135 | + <PanelBody title={__("Display options", "yatra")} initialOpen={false}> | |
| 136 | + <ToggleControl | |
| 137 | + label={__("Show trip count", "yatra")} | |
| 138 | + checked={attributes.show_trip_count} | |
| 139 | + onChange={(value: boolean) => | |
| 140 | + setAttributes({ show_trip_count: value }) | |
| 141 | + } | |
| 142 | + /> | |
| 143 | + <ToggleControl | |
| 144 | + label={__("Show description", "yatra")} | |
| 145 | + checked={attributes.show_description} | |
| 146 | + onChange={(value: boolean) => | |
| 147 | + setAttributes({ show_description: value }) | |
| 148 | + } | |
| 149 | + /> | |
| 150 | + <ToggleControl | |
| 151 | + label={__("Show image", "yatra")} | |
| 152 | + checked={attributes.show_image} | |
| 153 | + onChange={(value: boolean) => setAttributes({ show_image: value })} | |
| 154 | + /> | |
| 155 | + <ToggleControl | |
| 156 | + label={__("Hide empty destinations", "yatra")} | |
| 157 | + help={__( | |
| 158 | + "Skip destinations that have no published trips assigned. Off by default — turn on for a tighter live catalog, leave off for editorial / onboarding views.", | |
| 159 | + "yatra", | |
| 160 | + )} | |
| 161 | + checked={attributes.hide_empty} | |
| 162 | + onChange={(value: boolean) => setAttributes({ hide_empty: value })} | |
| 163 | + /> | |
| 164 | + <ToggleControl | |
| 165 | + label={__("Featured only (filter list)", "yatra")} | |
| 166 | + help={__( | |
| 167 | + "When on, only destinations marked as featured in Yatra → Destinations are listed.", | |
| 168 | + "yatra", | |
| 169 | + )} | |
| 170 | + checked={attributes.featured_only} | |
| 171 | + onChange={(value: boolean) => | |
| 172 | + setAttributes({ featured_only: value }) | |
| 76 | 173 | } |
| 77 | 174 | /> |
| 78 | 175 | </PanelBody> |
| 79 | 176 | </InspectorControls> |