PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.16
Yatra – Travel Booking & Tour Operator Software v3.0.16
3.0.16 3.0.15 3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 All 84 releases
← All changes | resources/js/pages/DiscountForm.tsx +45 -24 3.0.8 → 3.0.16 View file →
@@ -14,13 +14,19 @@
14 14 Trash2,
15 15 Users,
16 16 } from "lucide-react";
17 17 import { __ } from "../lib/i18n";
18 +import { toDateValue } from "../lib/dateFormat";
18 19 import { usePermissions } from "../hooks/usePermissions";
19 20 import { useToast } from "../components/ui/toast";
20 21 import { apiClient } from "../lib/api-client";
21 22 import { Button } from "../components/ui/button";
22 23 import { Input } from "../components/ui/input";
24 +import { getCurrencySymbol } from "../data/currencies";
25 +import {
26 + normalizeCurrencyPosition,
27 + readYatraCurrencyPositionFromWindow,
28 +} from "../lib/currency-display";
23 29 import { Select } from "../components/ui/select";
24 30 import { PageHeader } from "../components/common/PageHeader";
25 31 import {
26 32 Card,
@@ -82,8 +88,28 @@
82 88 const DiscountForm: React.FC = () => {
83 89 const queryClient = useQueryClient();
84 90 const { can, permissions, isPro } = usePermissions();
85 91 const { showToast } = useToast();
92 +
93 + // Currency symbol + placement for the amount fields, taken from the operator's
94 + // settings (localized into window.yatraAdmin). Previously these inputs
95 + // hardcoded "$" on the left, ignoring both the configured symbol and its
96 + // position (left / left_space / right / right_space).
97 + const currencySymbol = getCurrencySymbol(
98 + ((window as unknown as { yatraAdmin?: { currency?: string } })?.yatraAdmin
99 + ?.currency as string) || "USD",
100 + );
101 + const currencyOnRight = (() => {
102 + const pos = normalizeCurrencyPosition(readYatraCurrencyPositionFromWindow());
103 + return pos === "right" || pos === "right_space";
104 + })();
105 + const currencyPad = currencyOnRight
106 + ? currencySymbol.length > 1
107 + ? "pr-10"
108 + : "pr-7"
109 + : currencySymbol.length > 1
110 + ? "pl-10"
111 + : "pl-7";
86 112 const [showPremiumModal, setShowPremiumModal] = useState(false);
87 113 // Get initial discount_mode from URL at initialization time
88 114 const getInitialState = (): DiscountFormData => {
89 115 const params = new URLSearchParams(window.location.search);
@@ -580,9 +606,9 @@
580 606 // Valid from date can be in the past (backdating allowed)
581 607 // No validation needed for valid_from date
582 608
583 609 if (formData.expiry_date) {
584 - const expiryDate = new Date(formData.expiry_date);
610 + const expiryDate = toDateValue(formData.expiry_date);
585 611 if (expiryDate < today) {
586 612 newErrors.expiry_date = __(
587 613 "Expiry date cannot be in the past",
588 614 "yatra",
@@ -591,10 +617,10 @@
591 617 }
592 618
593 619 // Check if expiry date is after valid from date
594 620 if (formData.valid_from && formData.expiry_date) {
595 - const validFrom = new Date(formData.valid_from);
596 - const expiryDate = new Date(formData.expiry_date);
621 + const validFrom = toDateValue(formData.valid_from);
622 + const expiryDate = toDateValue(formData.expiry_date);
597 623 if (expiryDate < validFrom) {
598 624 newErrors.expiry_date = __(
599 625 "Expiry date must be after the valid from date",
600 626 "yatra",
@@ -1347,11 +1373,10 @@
1347 1373 required
1348 1374 />
1349 1375 ) : (
1350 1376 <div className="relative">
1351 - <span className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500 text-sm">
1352 - $
1353 - </span>
1377 + <span className={`absolute ${currencyOnRight ? "right-3" : "left-3"} top-1/2 transform -translate-y-1/2 text-gray-500 text-sm`}>
1378 + {currencySymbol} </span>
1354 1379 <Input
1355 1380 id="amount"
1356 1381 name="amount"
1357 1382 type="number"
@@ -1361,9 +1386,9 @@
1361 1386 onChange={(e) =>
1362 1387 handleFieldChange("amount", e.target.value)
1363 1388 }
1364 1389 placeholder={__("e.g., 50", "yatra")}
1365 - className={`pl-7 ${errors.amount ? "border-red-500" : ""}`}
1390 + className={`${currencyPad} ${errors.amount ? "border-red-500" : ""}`}
1366 1391 required
1367 1392 />
1368 1393 </div>
1369 1394 )}
@@ -1399,11 +1424,10 @@
1399 1424 )}
1400 1425 className="mb-2"
1401 1426 />
1402 1427 <div className="relative">
1403 - <span className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500 text-sm">
1404 - $
1405 - </span>
1428 + <span className={`absolute ${currencyOnRight ? "right-3" : "left-3"} top-1/2 transform -translate-y-1/2 text-gray-500 text-sm`}>
1429 + {currencySymbol} </span>
1406 1430 <Input
1407 1431 id="max_discount_amount"
1408 1432 type="number"
1409 1433 min="0"
@@ -1415,9 +1439,9 @@
1415 1439 e.target.value,
1416 1440 )
1417 1441 }
1418 1442 placeholder={__("e.g., 500 (optional)", "yatra")}
1419 - className={`pl-7 ${errors.max_discount_amount ? "border-red-500" : ""}`}
1443 + className={`${currencyPad} ${errors.max_discount_amount ? "border-red-500" : ""}`}
1420 1444 />
1421 1445 </div>
1422 1446 {errors.max_discount_amount && (
1423 1447 <p className="mt-1.5 text-sm text-red-600 dark:text-red-400 flex items-center gap-1">
@@ -1553,11 +1577,10 @@
1553 1577 )}
1554 1578 className="mb-2"
1555 1579 />
1556 1580 <div className="relative">
1557 - <span className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500 text-sm">
1558 - $
1559 - </span>
1581 + <span className={`absolute ${currencyOnRight ? "right-3" : "left-3"} top-1/2 transform -translate-y-1/2 text-gray-500 text-sm`}>
1582 + {currencySymbol} </span>
1560 1583 <Input
1561 1584 id="min_amount"
1562 1585 type="number"
1563 1586 min="0"
@@ -1566,9 +1589,9 @@
1566 1589 onChange={(e) =>
1567 1590 handleFieldChange("min_amount", e.target.value)
1568 1591 }
1569 1592 placeholder={__("e.g., 100", "yatra")}
1570 - className={`pl-7 ${errors.min_amount ? "border-red-500" : ""}`}
1593 + className={`${currencyPad} ${errors.min_amount ? "border-red-500" : ""}`}
1571 1594 />
1572 1595 </div>
1573 1596 {errors.min_amount && (
1574 1597 <p className="mt-1.5 text-sm text-red-600 dark:text-red-400 flex items-center gap-1">
@@ -1620,9 +1643,9 @@
1620 1643 }
1621 1644 placeholder={__("Select expiry date", "yatra")}
1622 1645 minDate={
1623 1646 formData.valid_from
1624 - ? new Date(formData.valid_from)
1647 + ? toDateValue(formData.valid_from)
1625 1648 : new Date()
1626 1649 }
1627 1650 error={!!errors.expiry_date}
1628 1651 className={errors.expiry_date ? "border-red-500" : ""}
@@ -1930,11 +1953,10 @@
1930 1953 </label>
1931 1954 <div className="relative">
1932 1955 {range.discount_type ===
1933 1956 "fixed" && (
1934 - <span className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500 text-sm">
1935 - $
1936 - </span>
1957 + <span className={`absolute ${currencyOnRight ? "right-3" : "left-3"} top-1/2 transform -translate-y-1/2 text-gray-500 text-sm`}>
1958 + {currencySymbol} </span>
1937 1959 )}
1938 1960 <Input
1939 1961 type="number"
1940 1962 min="0"
@@ -1959,9 +1981,9 @@
1959 1981 "percentage"
1960 1982 ? __("e.g., 10", "yatra")
1961 1983 : __("e.g., 50", "yatra")
1962 1984 }
1963 - className={`${range.discount_type === "fixed" ? "pl-7" : ""} ${errors[`group_discount_ranges_${idx}_amount`] ? "border-red-500" : ""}`}
1985 + className={`${range.discount_type === "fixed" ? currencyPad : ""} ${errors[`group_discount_ranges_${idx}_amount`] ? "border-red-500" : ""}`}
1964 1986 />
1965 1987 {range.discount_type ===
1966 1988 "percentage" && (
1967 1989 <span className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-500 text-sm">
@@ -2496,11 +2518,10 @@
2496 2518 </label>
2497 2519 <div className="relative">
2498 2520 {range.discount_type ===
2499 2521 "fixed" && (
2500 - <span className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500 text-sm">
2501 - $
2502 - </span>
2522 + <span className={`absolute ${currencyOnRight ? "right-3" : "left-3"} top-1/2 transform -translate-y-1/2 text-gray-500 text-sm`}>
2523 + {currencySymbol} </span>
2503 2524 )}
2504 2525 <Input
2505 2526 type="number"
2506 2527 min="0"
@@ -2537,9 +2558,9 @@
2537 2558 "e.g., 50",
2538 2559 "yatra",
2539 2560 )
2540 2561 }
2541 - className={`${range.discount_type === "fixed" ? "pl-7" : ""} ${errors[`category_discounts_${catIdx}_ranges_${rIdx}_amount`] ? "border-red-500" : ""}`}
2562 + className={`${range.discount_type === "fixed" ? currencyPad : ""} ${errors[`category_discounts_${catIdx}_ranges_${rIdx}_amount`] ? "border-red-500" : ""}`}
2542 2563 />
2543 2564 {range.discount_type ===
2544 2565 "percentage" && (
2545 2566 <span className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-500 text-sm">