| @@ -25,8 +25,13 @@ | ||
| 25 | 25 | } from "../components/ui/card"; |
| 26 | 26 | import { ConditionalRender } from "../components/ui/conditional-render"; |
| 27 | 27 | import { IconPicker, IconPickerValue } from "../components/ui/icon-picker"; |
| 28 | 28 | import { RichTextEditor } from "../components/ui/rich-text-editor"; |
| 29 | +import { | |
| 30 | + ClassificationLandingPageField, | |
| 31 | + fetchPublishedPagePermalink, | |
| 32 | + parseLandingPageIdFromMetadata, | |
| 33 | +} from "../components/classifications/ClassificationLandingPageField"; | |
| 29 | 34 | |
| 30 | 35 | interface DestinationFormData { |
| 31 | 36 | name: string; |
| 32 | 37 | slug: string; |
| @@ -38,8 +43,9 @@ | ||
| 38 | 43 | status: string; |
| 39 | 44 | seo_title: string; |
| 40 | 45 | seo_description: string; |
| 41 | 46 | seo_keywords: string; |
| 47 | + landing_page_id: number | null; | |
| 42 | 48 | } |
| 43 | 49 | |
| 44 | 50 | const DestinationForm: React.FC = () => { |
| 45 | 51 | const queryClient = useQueryClient(); |
| @@ -53,8 +59,9 @@ | ||
| 53 | 59 | status: "publish", |
| 54 | 60 | seo_title: "", |
| 55 | 61 | seo_description: "", |
| 56 | 62 | seo_keywords: "", |
| 63 | + landing_page_id: null, | |
| 57 | 64 | }); |
| 58 | 65 | const [errors, setErrors] = useState<Record<string, string>>({}); |
| 59 | 66 | const [isSubmitting, setIsSubmitting] = useState(false); |
| 60 | 67 | const [isSlugEditable, setIsSlugEditable] = useState(false); |
| @@ -115,8 +122,11 @@ | ||
| 115 | 122 | status: destinationData.status || "draft", |
| 116 | 123 | seo_title: destinationData.metadata?.seo_title || "", |
| 117 | 124 | seo_description: destinationData.metadata?.seo_description || "", |
| 118 | 125 | seo_keywords: destinationData.metadata?.seo_keywords || "", |
| 126 | + landing_page_id: parseLandingPageIdFromMetadata( | |
| 127 | + destinationData.metadata as { landing_page_id?: unknown }, | |
| 128 | + ), | |
| 119 | 129 | }); |
| 120 | 130 | } |
| 121 | 131 | }, [destinationData, isEditMode]); |
| 122 | 132 | |
| @@ -178,11 +188,11 @@ | ||
| 178 | 188 | } |
| 179 | 189 | |
| 180 | 190 | if (!formData.slug.trim()) { |
| 181 | 191 | newErrors.slug = __("Slug is required", "yatra"); |
| 182 | - } else if (!/^[a-z0-9-]+$/.test(formData.slug)) { | |
| 192 | + } else if (!/^[\p{L}\p{N}-]+$/u.test(formData.slug)) { | |
| 183 | 193 | newErrors.slug = __( |
| 184 | - "Slug can only contain lowercase letters, numbers, and hyphens", | |
| 194 | + "Slug can only contain letters, numbers, and hyphens", | |
| 185 | 195 | "yatra", |
| 186 | 196 | ); |
| 187 | 197 | } |
| 188 | 198 | |
| @@ -201,8 +211,9 @@ | ||
| 201 | 211 | status: data.status, |
| 202 | 212 | seo_title: data.seo_title.trim(), |
| 203 | 213 | seo_description: data.seo_description.trim(), |
| 204 | 214 | seo_keywords: data.seo_keywords.trim(), |
| 215 | + landing_page_id: data.landing_page_id ?? null, | |
| 205 | 216 | }; |
| 206 | 217 | |
| 207 | 218 | // If slug was manually edited, add flag to preserve it |
| 208 | 219 | if (isEditMode && isSlugEditable) { |
| @@ -343,9 +354,21 @@ | ||
| 343 | 354 | </Button> |
| 344 | 355 | {formData.slug && ( |
| 345 | 356 | <Button |
| 346 | 357 | variant="outline" |
| 347 | - onClick={() => { | |
| 358 | + onClick={async () => { | |
| 359 | + if ( | |
| 360 | + formData.landing_page_id && | |
| 361 | + window.yatraAdmin?.customLandingPagesModuleEnabled | |
| 362 | + ) { | |
| 363 | + const link = await fetchPublishedPagePermalink( | |
| 364 | + formData.landing_page_id, | |
| 365 | + ); | |
| 366 | + if (link) { | |
| 367 | + window.open(link, "_blank", "noopener,noreferrer"); | |
| 368 | + return; | |
| 369 | + } | |
| 370 | + } | |
| 348 | 371 | const targetUrl = buildYatraSinglePreviewUrl({ |
| 349 | 372 | entity: "destination", |
| 350 | 373 | slug: formData.slug || "", |
| 351 | 374 | bases: settings as Record<string, unknown> | null, |
| @@ -471,8 +494,16 @@ | ||
| 471 | 494 | maxHeight={720} |
| 472 | 495 | /> |
| 473 | 496 | </CardContent> |
| 474 | 497 | </Card> |
| 498 | + | |
| 499 | + <ClassificationLandingPageField | |
| 500 | + selectId="yatra-destination-landing-page" | |
| 501 | + value={formData.landing_page_id} | |
| 502 | + onChange={(id) => | |
| 503 | + setFormData((prev) => ({ ...prev, landing_page_id: id })) | |
| 504 | + } | |
| 505 | + /> | |
| 475 | 506 | </div> |
| 476 | 507 | |
| 477 | 508 | {/* Sidebar */} |
| 478 | 509 | <div className="space-y-3"> |