/** * Availability Form * Add or edit availability dates for a trip */ import React, { useState, useEffect } from "react"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { useNavigate } from "../hooks/useNavigate"; import { ArrowLeft, Save, Plus, X, Loader2, MapPin, CheckCircle2, } from "lucide-react"; import { __ } from "../lib/i18n"; import { Button } from "../components/ui/button"; import { Input } from "../components/ui/input"; import { Select } from "../components/ui/select"; import { PageHeader } from "../components/common/PageHeader"; import { Card, CardContent, CardHeader, CardTitle, CardDescription, } from "../components/ui/card"; import { HelpText } from "../components/ui/help-text"; import { Alert } from "../components/ui/alert"; import { AlertCircle } from "lucide-react"; import { DatePicker } from "../components/ui/date-picker"; import { TimePicker } from "../components/ui/time-picker"; import { apiClient } from "../lib/api-client"; import { useToast } from "../components/ui/toast"; import { AvailabilityFormSkeleton } from "../components/availability/AvailabilityFormSkeleton"; import { LocationPicker } from "../components/trip-form/LocationPicker"; function coordFromApi(v: unknown): string { if (v == null || v === "") return ""; return String(v); } interface PriceType { category_id: number; original_price: string; discounted_price: string; } interface TravelerCategory { id: number; label: string; description: string; status: "active" | "inactive" | "publish" | "draft"; age_min?: number; age_max?: number; } interface AvailabilityFormData { departure_date: string; departure_time: string; arrival_date: string; arrival_time: string; total_seats: string; // Total capacity booked_seats: string; // Currently booked (read-only in edit mode) seats_remaining: string; // Legacy field pricing_type: "regular" | "traveler_based"; original_price: string; discounted_price: string; price_types: PriceType[]; status: "available" | "sold_out" | "limited" | "closed" | "blocked"; is_blocked: boolean; // Blocked for maintenance/holidays block_reason: string; // Reason for blocking alert_threshold: string; // Alert when seats drop below this from_location: string; to_location: string; from_latitude: string; from_longitude: string; to_latitude: string; to_longitude: string; } const AvailabilityForm: React.FC = () => { const { navigate } = useNavigate(); const queryClient = useQueryClient(); const { showToast } = useToast(); // Get trip_id and id from URL const urlParams = new URLSearchParams(window.location.search); const tripIdFromUrl = urlParams.get("trip_id") ? parseInt(urlParams.get("trip_id")!) : null; const availabilityId = urlParams.get("id") || null; const isEditMode = !!availabilityId; // In edit mode, trip_id can come from availability data, so we'll use state const [tripId, setTripId] = useState(tripIdFromUrl); const [formData, setFormData] = useState({ departure_date: "", departure_time: "", arrival_date: "", arrival_time: "", total_seats: "", booked_seats: "0", seats_remaining: "", pricing_type: "regular", original_price: "", discounted_price: "", price_types: [], status: "available", is_blocked: false, block_reason: "", alert_threshold: "5", from_location: "", to_location: "", from_latitude: "", from_longitude: "", to_latitude: "", to_longitude: "", }); const [errors, setErrors] = useState< Partial> & { submit?: string; [key: string]: string | undefined; } >({}); const [showCategorySelector, setShowCategorySelector] = useState(false); // Fetch trip details const { data: tripData } = useQuery({ queryKey: ["trip", tripId], queryFn: async () => { if (!tripId) return null; const response = await apiClient.get(`/trips/${tripId}`); const data = response?.data || response; return data; }, enabled: !!tripId, }); // Fetch traveler categories const { data: categoriesData, isLoading: isLoadingCategories } = useQuery({ queryKey: ["traveler-categories"], queryFn: async () => { const response = await apiClient.get("/traveler-categories"); const categories = response?.data || response || []; return { categories: Array.isArray(categories) ? categories : [], }; }, }); // Filter for active categories - check both 'active' and 'publish' status const activeCategories = categoriesData?.categories?.filter( (cat: TravelerCategory) => cat.status === "active" || cat.status === "publish", ) || []; // Fetch existing availability data if editing const { data: availabilityData, isLoading: isLoadingAvailability } = useQuery( { queryKey: ["availability", availabilityId], queryFn: async () => { if (!availabilityId) return null; const response = await apiClient.get(`/availability/${availabilityId}`); return response?.data || response; }, enabled: isEditMode && !!availabilityId, }, ); // Set trip_id from availability data if not in URL (for edit mode) useEffect(() => { if (availabilityData && availabilityData.trip_id && !tripId) { setTripId(availabilityData.trip_id); } }, [availabilityData, tripId]); // Load form data when trip or availability data is available useEffect(() => { if (tripData && !isEditMode) { const rawPriceTypes = tripData.price_types; const hasTravelerPricing = Array.isArray(rawPriceTypes) ? rawPriceTypes.length > 0 : false; const effectivePricingType = hasTravelerPricing ? "traveler_based" : tripData.pricing_type || "regular"; setFormData((prev) => ({ ...prev, from_location: tripData.starting_location || "", to_location: tripData.ending_location || "", from_latitude: coordFromApi(tripData.starting_latitude), from_longitude: coordFromApi(tripData.starting_longitude), to_latitude: coordFromApi(tripData.ending_latitude), to_longitude: coordFromApi(tripData.ending_longitude), // Default pricing type based on trip's pricing type pricing_type: effectivePricingType as "regular" | "traveler_based", })); } }, [tripData, isEditMode]); useEffect(() => { if (availabilityData) { const totalSeats = availabilityData.total_seats || availabilityData.seats_total || 0; const availableSeats = availabilityData.available_seats || availabilityData.seats_available || 0; const bookedSeats = totalSeats - availableSeats; // ALWAYS use trip's pricing type, not the old availability pricing type // This ensures availability dates match the current trip pricing configuration const rawTripPriceTypes = tripData?.price_types; const tripHasTravelerPricing = Array.isArray(rawTripPriceTypes) ? rawTripPriceTypes.length > 0 : false; const pricingType = tripHasTravelerPricing ? "traveler_based" : tripData?.pricing_type || availabilityData.pricing_type || "regular"; setFormData({ departure_date: availabilityData.departure_date || "", departure_time: availabilityData.departure_time || "", arrival_date: availabilityData.arrival_date || availabilityData.departure_date || "", arrival_time: availabilityData.arrival_time || "", total_seats: totalSeats.toString(), booked_seats: bookedSeats.toString(), seats_remaining: availableSeats > 10 ? "10+" : availableSeats.toString(), pricing_type: pricingType as "regular" | "traveler_based", original_price: availabilityData.original_price?.toString() || "", discounted_price: availabilityData.discounted_price?.toString() || "", price_types: availabilityData.price_types || [], status: (availabilityData.status || (availabilityData.is_blocked ? "blocked" : "available")) as | "available" | "sold_out" | "limited" | "closed" | "blocked", is_blocked: availabilityData.is_blocked || availabilityData.status === "blocked" || false, block_reason: availabilityData.block_reason || "", alert_threshold: availabilityData.alert_threshold?.toString() || "5", from_location: availabilityData.from_location || tripData?.starting_location || "", to_location: availabilityData.to_location || tripData?.ending_location || "", from_latitude: coordFromApi(availabilityData.from_latitude) || coordFromApi(tripData?.starting_latitude), from_longitude: coordFromApi(availabilityData.from_longitude) || coordFromApi(tripData?.starting_longitude), to_latitude: coordFromApi(availabilityData.to_latitude) || coordFromApi(tripData?.ending_latitude), to_longitude: coordFromApi(availabilityData.to_longitude) || coordFromApi(tripData?.ending_longitude), }); } }, [availabilityData, tripData]); const handleFieldChange = ( field: keyof AvailabilityFormData, value: string | boolean, ) => { setFormData((prev) => ({ ...prev, [field]: value, })); // Clear error for this field if (errors[field]) { setErrors((prev) => { const newErrors = { ...prev }; delete newErrors[field]; return newErrors; }); } }; const handlePriceTypeAdd = (categoryId: number) => { // Check if category already exists if (formData.price_types.some((pt) => pt.category_id === categoryId)) { return; } // Find the category to get its label const category = activeCategories.find((cat) => cat.id === categoryId); setFormData((prev) => ({ ...prev, price_types: [ ...prev.price_types, { category_id: categoryId, category_label: category?.label || "", original_price: "", discounted_price: "", }, ], })); }; const handlePriceTypeRemove = (categoryId: number) => { setFormData((prev) => ({ ...prev, price_types: prev.price_types.filter( (pt) => pt.category_id !== categoryId, ), })); }; const handlePriceTypeChange = ( categoryId: number, field: "original_price" | "discounted_price", value: string, ) => { setFormData((prev) => ({ ...prev, price_types: prev.price_types.map((pt) => pt.category_id === categoryId ? { ...pt, [field]: value } : pt, ), })); }; const validateForm = (): boolean => { const newErrors: Partial> & { [key: string]: string; } = {}; if (!formData.departure_date) { newErrors.departure_date = __("Departure date is required", "yatra"); } if (!formData.arrival_date) { newErrors.arrival_date = __("Arrival date is required", "yatra"); } // Validate dates and times based on trip type const isSingleDay = tripData?.trip_type === "single_day"; if (isSingleDay) { // For single day trips, both dates should be the same if ( formData.departure_date && formData.arrival_date && formData.departure_date !== formData.arrival_date ) { newErrors.arrival_date = __( "For single day trips, departure and arrival must be on the same date", "yatra", ); } // Validate times if (!formData.departure_time) { newErrors.departure_time = __( "Departure time is required for single day trips", "yatra", ); } if (!formData.arrival_time) { newErrors.arrival_time = __( "Arrival time is required for single day trips", "yatra", ); } // Validate that arrival time is after departure time if ( formData.departure_time && formData.arrival_time && formData.departure_date === formData.arrival_date ) { const [depHour, depMin] = formData.departure_time .split(":") .map(Number); const [arrHour, arrMin] = formData.arrival_time.split(":").map(Number); const depMinutes = depHour * 60 + depMin; const arrMinutes = arrHour * 60 + arrMin; if (arrMinutes <= depMinutes) { newErrors.arrival_time = __( "Arrival time must be after departure time", "yatra", ); } } } else { // For multi-day trips, validate dates if (formData.departure_date && formData.arrival_date) { const departure = new Date(formData.departure_date); const arrival = new Date(formData.arrival_date); if (arrival <= departure) { newErrors.arrival_date = __( "Arrival date must be after departure date", "yatra", ); } } } // Validate inventory if (!formData.total_seats || parseInt(formData.total_seats) <= 0) { newErrors.total_seats = __( "Total capacity is required and must be greater than 0", "yatra", ); } if (isEditMode && formData.booked_seats) { const total = parseInt(formData.total_seats) || 0; const booked = parseInt(formData.booked_seats) || 0; if (booked > total) { newErrors.booked_seats = __( "Booked seats cannot exceed total capacity", "yatra", ); } } // Validate pricing based on pricing type (OPTIONAL - only validate if provided) if (formData.pricing_type === "regular") { // Only validate if user has entered a price (optional override) if (formData.original_price && parseFloat(formData.original_price) <= 0) { newErrors.original_price = __( "Original price must be greater than 0", "yatra", ); } if ( formData.discounted_price && formData.original_price && parseFloat(formData.discounted_price) >= parseFloat(formData.original_price) ) { newErrors.discounted_price = __( "Discounted price must be less than original price", "yatra", ); } } else { // Validate price types only if provided (optional override) if (formData.price_types.length > 0) { formData.price_types.forEach((priceType, index) => { if ( priceType.original_price && (isNaN(parseFloat(priceType.original_price)) || parseFloat(priceType.original_price) < 0) ) { newErrors[`price_type_${index}_original`] = __( "Original price must be a valid number", "yatra", ); } if ( priceType.discounted_price && (isNaN(parseFloat(priceType.discounted_price)) || parseFloat(priceType.discounted_price) < 0) ) { newErrors[`price_type_${index}_discounted`] = __( "Discounted price must be a valid number", "yatra", ); } if ( priceType.discounted_price && priceType.original_price && parseFloat(priceType.discounted_price) >= parseFloat(priceType.original_price) ) { newErrors[`price_type_${index}_discounted`] = __( "Discounted price must be less than original price", "yatra", ); } }); } } setErrors(newErrors); return Object.keys(newErrors).length === 0; }; const saveMutation = useMutation({ mutationFn: async (data: AvailabilityFormData) => { const totalSeats = data.total_seats ? parseInt(data.total_seats) : 0; const bookedSeats = isEditMode && data.booked_seats ? parseInt(data.booked_seats) : 0; const availableSeats = totalSeats - bookedSeats; const payload = { trip_id: tripId, departure_date: data.departure_date, departure_time: tripData?.trip_type === "single_day" ? data.departure_time || null : null, arrival_date: data.arrival_date || null, arrival_time: tripData?.trip_type === "single_day" ? data.arrival_time || null : null, seats_total: totalSeats, seats_available: availableSeats, seats_reserved: 0, seats_waitlist: 0, pricing_type: data.pricing_type, original_price: data.pricing_type === "regular" && data.original_price ? parseFloat(data.original_price) : null, discounted_price: data.pricing_type === "regular" && data.discounted_price ? parseFloat(data.discounted_price) : null, price_types: data.pricing_type === "traveler_based" ? data.price_types : null, status: data.is_blocked ? "blocked" : data.status, from_location: data.from_location || null, to_location: data.to_location || null, from_latitude: data.from_latitude?.trim() || null, from_longitude: data.from_longitude?.trim() || null, to_latitude: data.to_latitude?.trim() || null, to_longitude: data.to_longitude?.trim() || null, special_notes: null, cutoff_hours: 24, alert_threshold: data.alert_threshold ? parseInt(data.alert_threshold) : null, is_blocked: data.is_blocked, block_reason: data.is_blocked ? data.block_reason || null : null, }; if (isEditMode && availabilityId) { const response = await apiClient.put( `/availability/${availabilityId}`, payload, ); return response?.data || response; } else { const response = await apiClient.post("/availability", payload); return response?.data || response; } }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["availability"] }); queryClient.invalidateQueries({ queryKey: ["trips"] }); // Navigate immediately, toast will be shown on the availability page if needed navigate({ subpage: "trips", tab: "availability", trip_id: tripId?.toString(), }); // Show toast after a brief delay to ensure navigation happens first setTimeout(() => { showToast( isEditMode ? __("Availability date updated successfully", "yatra") : __("Availability date created successfully", "yatra"), "success", 3000, // Shorter duration ); }, 100); }, onError: (error: any) => { const errorMessage = error?.message || error?.data?.message || __("An error occurred while saving", "yatra"); showToast(errorMessage, "error"); setErrors({ submit: errorMessage, }); }, }); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!validateForm()) { return; } saveMutation.mutate(formData); }; const getCurrencySymbol = (currency: string) => { const symbols: Record = { USD: "$", EUR: "€", GBP: "£", INR: "₹", }; return symbols[currency] || currency; }; // Show loading if we're in edit mode and waiting for availability data to get trip_id if (isEditMode && !tripId && isLoadingAvailability) { return ; } if (!tripId) { return (

{__("Trip ID Required", "yatra")}

{__("Please select a trip first.", "yatra")}

); } // Show skeleton loader while loading data if (isLoadingAvailability || (isEditMode && !availabilityData)) { return ; } return (
navigate({ subpage: "trips", tab: "availability", trip_id: tripId.toString(), }) } > {__("Back", "yatra")} ) : null } />
{__("Date Information", "yatra")} {__( "Set the departure and arrival dates for this availability", "yatra", )} {tripData?.trip_type === "single_day" ? ( // Single Day Trip - Show date and time pickers <>
{ handleFieldChange("departure_date", value); handleFieldChange("arrival_date", value); // Same date for single day }} placeholder={__("Select date", "yatra")} error={!!errors.departure_date} /> {errors.departure_date && (

{errors.departure_date}

)}
handleFieldChange("departure_time", value) } placeholder={__("Select departure time", "yatra")} error={!!errors.departure_time} /> {errors.departure_time && (

{errors.departure_time}

)}
handleFieldChange("arrival_time", value) } placeholder={__("Select arrival time", "yatra")} error={!!errors.arrival_time} /> {errors.arrival_time && (

{errors.arrival_time}

)}
) : ( // Multi-Day Trip - Show date pickers only
handleFieldChange("departure_date", value) } placeholder={__("Select departure date", "yatra")} error={!!errors.departure_date} /> {errors.departure_date && (

{errors.departure_date}

)}
handleFieldChange("arrival_date", value) } minDate={ formData.departure_date ? new Date(formData.departure_date) : undefined } placeholder={__("Select arrival date", "yatra")} error={!!errors.arrival_date} /> {errors.arrival_date && (

{errors.arrival_date}

)} {tripData?.duration_days && formData.departure_date && formData.arrival_date && (
{(() => { const departure = new Date(formData.departure_date); const arrival = new Date(formData.arrival_date); const selectedDays = Math.ceil( (arrival.getTime() - departure.getTime()) / (1000 * 60 * 60 * 24), ); const expectedDays = tripData.duration_days; const diff = selectedDays - expectedDays; if (diff === 0) { return (

{__("Duration matches trip duration", "yatra")}{" "} ({selectedDays} {__("days", "yatra")})

); } else if (diff < 0) { return (

{__("Shorter than trip duration", "yatra")}:{" "} {selectedDays} {__("days", "yatra")} ( {Math.abs(diff)} {__("days shorter", "yatra")}{" "} than expected {expectedDays}{" "} {__("days", "yatra")})

); } else { return (

{__("Longer than trip duration", "yatra")}:{" "} {selectedDays} {__("days", "yatra")} ({diff}{" "} {__("days longer", "yatra")} than expected{" "} {expectedDays} {__("days", "yatra")})

); } })()}
)} {tripData?.duration_days && !formData.arrival_date && ( )}
)}

{__("Starting Point", "yatra")}

{__("Where the journey begins", "yatra")}

{formData.from_latitude && formData.from_longitude && (
)}
{ setFormData((prev) => ({ ...prev, from_location: loc.name, from_latitude: loc.latitude, from_longitude: loc.longitude, })); }} label="" placeholder={__("Search for starting location...", "yatra")} helpText="" required={false} defaultMapCenter={ formData.from_latitude && formData.from_longitude ? [ parseFloat(formData.from_latitude), parseFloat(formData.from_longitude), ] : tripData?.starting_latitude && tripData?.starting_longitude ? [ parseFloat(String(tripData.starting_latitude)), parseFloat(String(tripData.starting_longitude)), ] : [20, 0] } defaultZoom={ formData.from_latitude && formData.from_longitude ? 13 : tripData?.starting_latitude && tripData?.starting_longitude ? 13 : 2 } mapHeight="300px" showMapButton={false} searchLimit={8} __={__} className="" mapClassName="rounded-lg" showManualCoordinateFields />

{__("Ending Point", "yatra")}

{__("Where the journey concludes", "yatra")}

{formData.to_latitude && formData.to_longitude && (
)}
{ setFormData((prev) => ({ ...prev, to_location: loc.name, to_latitude: loc.latitude, to_longitude: loc.longitude, })); }} label="" placeholder={__("Search for ending location...", "yatra")} helpText="" required={false} defaultMapCenter={ formData.to_latitude && formData.to_longitude ? [ parseFloat(formData.to_latitude), parseFloat(formData.to_longitude), ] : tripData?.ending_latitude && tripData?.ending_longitude ? [ parseFloat(String(tripData.ending_latitude)), parseFloat(String(tripData.ending_longitude)), ] : formData.from_latitude && formData.from_longitude ? [ parseFloat(formData.from_latitude), parseFloat(formData.from_longitude), ] : tripData?.starting_latitude && tripData?.starting_longitude ? [ parseFloat( String(tripData.starting_latitude), ), parseFloat( String(tripData.starting_longitude), ), ] : [20, 0] } defaultZoom={ formData.to_latitude && formData.to_longitude ? 13 : tripData?.ending_latitude && tripData?.ending_longitude ? 13 : formData.from_latitude && formData.from_longitude ? 13 : tripData?.starting_latitude && tripData?.starting_longitude ? 13 : 2 } mapHeight="300px" showMapButton={false} searchLimit={8} __={__} className="" mapClassName="rounded-lg" showManualCoordinateFields />
{__("Pricing & Availability", "yatra")} {__( "Set pricing for traveler categories and seat availability for this date", "yatra", )} {/* Pricing Override Info */}

{__("Pricing Override (Optional)", "yatra")}

{__( "Leave pricing fields empty to use the trip's default pricing. Fill them in only if you want to override the default pricing for this specific date.", "yatra", )}

{/* Pricing Type Info - Inherited from Trip */}
{formData.pricing_type === "traveler_based" ? ( ) : ( )}

{formData.pricing_type === "traveler_based" ? __("Traveler-Based Pricing", "yatra") : __("Regular Pricing", "yatra")}

{formData.pricing_type === "traveler_based" ? __( "This trip uses traveler category pricing. Set prices for each category below.", "yatra", ) : __( "This trip uses regular pricing. Set a single price for all travelers below.", "yatra", )}

{/* Regular Pricing */} {formData.pricing_type === "regular" && (
{getCurrencySymbol(tripData?.currency || "USD")} handleFieldChange("original_price", e.target.value) } placeholder="0.00" className={`pl-7 ${errors.original_price ? "border-red-500" : ""}`} />
{errors.original_price && (

{errors.original_price}

)} {!formData.original_price && tripData && (

{__("Using trip default", "yatra")}:{" "} {getCurrencySymbol(tripData?.currency || "USD")} {tripData.original_price || "0.00"}

)}
{getCurrencySymbol(tripData?.currency || "USD")} handleFieldChange("discounted_price", e.target.value) } placeholder="0.00" className={`pl-7 ${errors.discounted_price ? "border-red-500" : ""}`} />
{errors.discounted_price && (

{errors.discounted_price}

)}
)} {/* Traveler Category Pricing */} {formData.pricing_type === "traveler_based" && (

{__( "Add pricing to override trip default pricing for specific traveler categories. Leave empty to use trip default pricing.", "yatra", )}

{isLoadingCategories ? (
) : activeCategories.length === 0 ? (

{__("No active traveler categories found.", "yatra")}

) : (
{/* Add Pricing Button */}
{/* Category Selection Dropdown */} {showCategorySelector && ( <>
setShowCategorySelector(false)} />
{__( "Select a category to add pricing", "yatra", )}
{activeCategories.filter( (cat) => !formData.price_types.some( (pt) => pt.category_id === cat.id, ), ).length === 0 ? (
{__( "All categories have pricing added", "yatra", )}
) : (
{activeCategories .filter( (cat) => !formData.price_types.some( (pt) => pt.category_id === cat.id, ), ) .map((category: TravelerCategory) => { const ageRange = category.age_min !== undefined || category.age_max !== undefined ? category.age_min !== undefined && category.age_max !== undefined ? `${category.age_min}-${category.age_max} ${__("years", "yatra")}` : category.age_min !== undefined ? `${category.age_min}+ ${__("years", "yatra")}` : category.age_max !== undefined ? `${__("Under", "yatra")} ${category.age_max} ${__("years", "yatra")}` : "" : null; return ( ); })}
)}
)}
{/* Added Pricing List */} {formData.price_types.length > 0 && (
{formData.price_types.map((priceType, index) => { const category = activeCategories.find( (cat) => cat.id === priceType.category_id, ); if (!category) return null; return (

{category.label} {(category.age_min !== undefined || category.age_max !== undefined) && ( ( {category.age_min !== undefined && category.age_max !== undefined ? `${category.age_min}-${category.age_max} ${__("years", "yatra")}` : category.age_min !== undefined ? `${category.age_min}+ ${__("years", "yatra")}` : category.age_max !== undefined ? `${__("Under", "yatra")} ${category.age_max} ${__("years", "yatra")}` : ""} ) )}

{category.description}

{getCurrencySymbol( tripData?.currency || "USD", )} handlePriceTypeChange( category.id, "original_price", e.target.value, ) } placeholder="0.00" className={`pl-7 ${errors[`price_type_${index}_original`] ? "border-red-500" : ""}`} />
{errors[`price_type_${index}_original`] && (

{errors[`price_type_${index}_original`]}

)}
{getCurrencySymbol( tripData?.currency || "USD", )} handlePriceTypeChange( category.id, "discounted_price", e.target.value, ) } placeholder="0.00" className={`pl-7 ${errors[`price_type_${index}_discounted`] ? "border-red-500" : ""}`} />
{errors[`price_type_${index}_discounted`] && (

{errors[`price_type_${index}_discounted`]}

)}
); })}
)} {errors.price_types && (

{errors.price_types}

)}
)}
)} {/* Inventory Management */}

{__("Inventory Management", "yatra")}

handleFieldChange("total_seats", e.target.value) } placeholder="20" className={errors.total_seats ? "border-red-500" : ""} /> {errors.total_seats && (

{errors.total_seats}

)}
{isEditMode && (
)}
handleFieldChange("alert_threshold", e.target.value) } placeholder="5" />
{/* Block Date */}

{__("Block Date", "yatra")}

{formData.is_blocked && (
handleFieldChange("block_reason", e.target.value) } placeholder={__( "e.g., Maintenance, Holiday, Special Event", "yatra", )} />
)}
{/* Status */}
{formData.is_blocked && ( )}
{errors.submit && (

{errors.submit}

)}
); }; export default AvailabilityForm;