diff --git a/public/locales/ar/common.json b/public/locales/ar/common.json index b138874..14bbc7d 100644 --- a/public/locales/ar/common.json +++ b/public/locales/ar/common.json @@ -218,5 +218,14 @@ "noChanges": "لم يتم اكتشاف أي تغييرات.", "errorGeneric": "حدث خطأ ما. يرجى المحاولة مرة أخرى.", "errorUnknown": "حدث خطأ غير معروف.", - "benefits": "الفوائد" + "benefits": "الفوائد", + "Type of place": "نوع المكان", + "Rooms and Beds": "الغرف والأسِرَّة", + "Beds": "أسِرَّة", + "Bedrooms": "غرف النوم", + "Bathrooms": "الحمامات", + "$": "$", + "apply": "تطبيق", + "moreFilters": "المزيد من الفلاتر", + "clear": "مسح" } diff --git a/public/locales/ar/form.json b/public/locales/ar/form.json index 918769e..16aa29d 100644 --- a/public/locales/ar/form.json +++ b/public/locales/ar/form.json @@ -87,5 +87,7 @@ "uploadedImage": "الصورة المرفوعة", "delete": "حذف", "currentReceipt": "الإيصال الحالي", - "copy": "نسخ" + "copy": "نسخ", + "uploadPassword" : "قم برفع صورة جواز السفر هنا" + } diff --git a/public/locales/ar/navigation.json b/public/locales/ar/navigation.json index abd5950..ff5cf7c 100644 --- a/public/locales/ar/navigation.json +++ b/public/locales/ar/navigation.json @@ -11,5 +11,9 @@ "navAccount": "الحساب", "navMyTrips": "رحلاتي", "navPassengersList": "قائمة الركاب", - "navBills": "الفواتير" + "navBills": "الفواتير", + "discover-articles": "اكتشف أبرز المقالات حول جميع مواضيع الحياة. اكتب قصصك وشاركها", + "custom-trip": "رحلة مخصصة", + "Where to?": "إلى أين؟", + "Anywhere • Any week • Add guests": "في أي مكان • أي أسبوع • أضف الضيوف" } diff --git a/public/locales/en/common.json b/public/locales/en/common.json index c871980..3b1731f 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -219,5 +219,14 @@ "noChanges": "No changes detected.", "errorGeneric": "Something went wrong. Please try again.", "errorUnknown": "An unknown error occurred.", - "benefits" : "BENEFITS" + "benefits" : "BENEFITS", + "Type of place": "Type of place", + "Rooms and Beds": "Rooms and Beds", + "Beds": "Beds", + "Bedrooms": "Bedrooms", + "Bathrooms": "Bathrooms", + "$": "$", + "apply" : "Apply", + "moreFilters": "More Filters", + "clear" : "Clear" } diff --git a/public/locales/en/form.json b/public/locales/en/form.json index dfe425a..758f4a1 100644 --- a/public/locales/en/form.json +++ b/public/locales/en/form.json @@ -87,5 +87,6 @@ "uploadedImage": "Uploaded Image", "delete": "Delete", "currentReceipt": "Current Receipt", - "copy": "Copy" + "copy": "Copy", + "uploadPassword" : "Upload Passport Image Here" } diff --git a/public/locales/en/navigation.json b/public/locales/en/navigation.json index e02ff8d..a26acb4 100644 --- a/public/locales/en/navigation.json +++ b/public/locales/en/navigation.json @@ -11,5 +11,9 @@ "navAccount": "Account", "navMyTrips": "My Trips", "navPassengersList": "Passengers List", - "navBills": "Bills" + "navBills": "Bills", + "discover-articles": "Discover the most outstanding articles on all topics of life. Write your stories and share them", + "custom-trip": "Custom Trip", + "Where to?": "Where to?", + "Anywhere • Any week • Add guests": "Anywhere • Any week • Add guests" } diff --git a/public/locales/id/common.json b/public/locales/id/common.json index 464bfa2..9699b2e 100644 --- a/public/locales/id/common.json +++ b/public/locales/id/common.json @@ -218,5 +218,14 @@ "noChanges": "Tidak ada perubahan yang terdeteksi.", "errorGeneric": "Terjadi kesalahan. Silakan coba lagi.", "errorUnknown": "Terjadi kesalahan yang tidak diketahui.", - "benefits": "MANFAAT" + "benefits": "MANFAAT", + "Type of place": "Jenis tempat", + "Rooms and Beds": "Kamar dan Tempat Tidur", + "Beds": "Tempat Tidur", + "Bedrooms": "Kamar Tidur", + "Bathrooms": "Kamar Mandi", + "$": "$", + "apply": "Terapkan", + "moreFilters": "Lebih Banyak Filter", + "clear": "Bersihkan" } diff --git a/public/locales/id/form.json b/public/locales/id/form.json index 78bef01..4ee38f0 100644 --- a/public/locales/id/form.json +++ b/public/locales/id/form.json @@ -87,5 +87,7 @@ "uploadedImage": "Gambar yang diunggah", "delete": "Hapus", "currentReceipt": "Tanda Terima Saat Ini", - "copy": "Salin" + "copy": "Salin", + "uploadPassword" : "Unggah Gambar Paspor Di Sini" + } diff --git a/public/locales/id/navigation.json b/public/locales/id/navigation.json index e6d0d1a..3ec7ef9 100644 --- a/public/locales/id/navigation.json +++ b/public/locales/id/navigation.json @@ -11,5 +11,9 @@ "navAccount": "Akun", "navMyTrips": "Perjalanan Saya", "navPassengersList": "Daftar Penumpang", - "navBills": "Tagihan" + "navBills": "Tagihan", + "discover-articles": "Temukan artikel paling menonjol tentang semua topik kehidupan. Tulis cerita Anda dan bagikan", + "custom-trip": "Perjalanan Khusus", + "Where to?": "Kemana?", + "Anywhere • Any week • Add guests": "Dimana saja • Minggu apa saja • Tambahkan tamu" } diff --git a/public/locales/ru/common.json b/public/locales/ru/common.json index 932c1a9..0765a84 100644 --- a/public/locales/ru/common.json +++ b/public/locales/ru/common.json @@ -218,5 +218,14 @@ "noChanges": "Изменения не обнаружены.", "errorGeneric": "Произошла ошибка. Пожалуйста, попробуйте снова.", "errorUnknown": "Произошла неизвестная ошибка.", - "benefits": "ПРЕИМУЩЕСТВА" + "benefits": "ПРЕИМУЩЕСТВА", + "Type of place": "Тип места", + "Rooms and Beds": "Комнаты и кровати", + "Beds": "Кровати", + "Bedrooms": "Спальни", + "Bathrooms": "Ванные комнаты", + "$": "$", + "apply": "Применить", + "moreFilters": "Больше фильтров", + "clear": "Очистить" } diff --git a/public/locales/ru/navigation.json b/public/locales/ru/navigation.json index ee0e828..c289778 100644 --- a/public/locales/ru/navigation.json +++ b/public/locales/ru/navigation.json @@ -11,5 +11,10 @@ "navAccount": "Аккаунт", "navMyTrips": "Мои поездки", "navPassengersList": "Список пассажиров", - "navBills": "Счета" + "navBills": "Счета", + "uploadPassword": "Загрузите изображение паспорта здесь", + "discover-articles": "Откройте для себя самые выдающиеся статьи на все темы жизни. Пишите свои истории и делитесь ими", + "custom-trip": "Индивидуальная поездка", + "Where to?": "Куда?", + "Anywhere • Any week • Add guests": "В любом месте • Любая неделя • Добавить гостей" } diff --git a/src/app/[locale]/(account-pages)/bills/BillCard.tsx b/src/app/[locale]/(account-pages)/bills/BillCard.tsx index 9c43758..453b576 100644 --- a/src/app/[locale]/(account-pages)/bills/BillCard.tsx +++ b/src/app/[locale]/(account-pages)/bills/BillCard.tsx @@ -37,7 +37,14 @@ interface BillCardProps { bill: Bill; onViewDetail: (bill: Bill) => void; } - +const formatDate = (dateString: string): string => { + const date = new Date(dateString); + return date.toLocaleDateString("en-US", { + day: "2-digit", + month: "short", + year: "numeric", + }); +}; const BillCard: React.FC = ({ bill, onViewDetail }) => { const { t } = useTranslation("form"); @@ -65,7 +72,7 @@ const BillCard: React.FC = ({ bill, onViewDetail }) => { }; return ( -
+
onViewDetail(bill)} className="bg-white shadow-md rounded-lg p-4 mb-4 dark:bg-neutral-800">

{bill.service.includes("tour") && } @@ -80,11 +87,11 @@ const BillCard: React.FC = ({ bill, onViewDetail }) => {
{t("issuedDate")}: - {bill.created_at} + {formatDate(bill.created_at)}
{t("expirationDate")}: - {bill.expiration_date} + {formatDate(bill.expiration_date)}
{t("tourInvoiceAmount")}: @@ -92,7 +99,7 @@ const BillCard: React.FC = ({ bill, onViewDetail }) => {
- onViewDetail(bill)} className="mt-4"> + {t("viewBill")}

diff --git a/src/app/[locale]/(account-pages)/bills/[slug]/page.tsx b/src/app/[locale]/(account-pages)/bills/[slug]/page.tsx index c343c66..c69d6c4 100644 --- a/src/app/[locale]/(account-pages)/bills/[slug]/page.tsx +++ b/src/app/[locale]/(account-pages)/bills/[slug]/page.tsx @@ -1,6 +1,6 @@ "use client"; -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import axiosInstance from "@/components/api/axios"; import ButtonPrimary from "@/shared/ButtonPrimary"; import Button from "@/shared/Button"; @@ -10,6 +10,9 @@ import getImageURL from "@/components/api/getImageURL"; import { toast, ToastContainer } from "react-toastify"; import Image from "next/image"; import { useTranslation } from "react-i18next"; +import { BiCloudUpload } from "react-icons/bi"; +import { HiOutlineTrash } from "react-icons/hi"; +import { useRouter } from "next/router"; export type BillStatus = | "awaiting_payment" @@ -33,44 +36,59 @@ export interface Bill { src: string; }; detail_service: { - passenger_counts: { adults: string; children: string; infants: string }; + passenger_data: { + adults: { count: number; names: string[] }; + children: { count: number; names: string[] }; + infants: { count: number; names: string[] }; + }; }; - transaction_receipt: string; + transaction_receipt: string | null; card_number: string | number; } interface BillDetailCardProps { - bill: Bill; + billId: number; } -const statusStyles: { [key in BillStatus]: JSX.Element } = { - awaiting_payment: ( - - {"t('awaitingPayment')"} - - ), - approved: ( - - {"t('approved')"} - - ), - rejected: ( - - {"t('rejected')"} - - ), - pending: ( - - {"t('pending')"} - - ), + +const formatDate = (dateString: string): string => { + const date = new Date(dateString); + return date.toLocaleDateString("en-US", { + day: "2-digit", + month: "short", + year: "numeric", + }); }; -const BillDetailCard: React.FC = ({ bill }) => { - const [uploadedFile, setUploadedFile] = useState(null); +const BillDetailCard: React.FC = ({ billId }) => { + const [bill, setBill] = useState(null); + const [uploadedFile, setUploadedFile] = useState(null); const [loadingUpload, setLoadingUpload] = useState(false); const [loading, setLoading] = useState(false); const { user } = useUserContext(); const { t } = useTranslation("form"); + + const statusStyles: { [key in BillStatus]: JSX.Element } = { + awaiting_payment: ( + + {t("awaitingPayment")} + + ), + approved: ( + + {t("approved")} + + ), + rejected: ( + + {t("rejected")} + + ), + pending: ( + + {t("pending")} + + ), + }; const handleFileChange = async (e: React.ChangeEvent) => { setLoadingUpload(true); const file = e.target.files?.[0]; @@ -80,13 +98,30 @@ const BillDetailCard: React.FC = ({ bill }) => { setLoadingUpload(false); } }; + const getBillData = async () => { + try { + const response = await axiosInstance(`/api/factors/${billId}/`, { + headers: { + Authorization: `token ${user.token}`, + }, + }); + setBill(response.data); + } catch (error) { + console.error(error); + toast.error(t("errorFetchingBillData")); + } + }; + + useEffect(() => { + getBillData(); + }, [billId]); const handleSubmit = () => { setLoading(true); if (uploadedFile) { axiosInstance .patch( - `/api/factors/update/${bill.id}/`, + `/api/factors/update/${billId}/`, { transaction_receipt: uploadedFile, }, @@ -99,10 +134,10 @@ const BillDetailCard: React.FC = ({ bill }) => { .then(() => { toast.success(t("transactionReceiptUpdated")); setLoading(false); + setUploadedFile(null); }) .catch((error) => { - console.log(error); - + console.error(error); toast.error(t("updateFailed")); setLoading(false); }); @@ -111,45 +146,90 @@ const BillDetailCard: React.FC = ({ bill }) => { } }; + const handleDeleteFile = () => { + setLoading(true); + if (uploadedFile) { + setUploadedFile(null); + setLoading(false); + } else { + axiosInstance + .post( + `/api/factors/clear-receipt/${billId}/`, + {}, + { + headers: { + Authorization: `token ${user.token}`, + }, + } + ) + .then(() => { + toast.success(t("transactionReceiptDeleted")); + }) + .catch((error) => { + console.error(error); + toast.error(t("errorOccurred")); + }) + .finally(() => { + setLoading(false); + useRouter().reload(); + }); + } + }; + + if (!bill) { + return

{t("loadingBillData")}

; + } + return (
-

{bill.title}

+

+ {bill.title || t("billDetails")} +

{statusStyles[bill.status]}
- {bill.message && ( + {bill.rejected_description && (

{t("whyRejected")}

-

{bill.message}

+

{bill.rejected_description}

)}
{t("issuedDate")}: - {bill.created_at} + {formatDate(bill.created_at)}
{t("expirationDate")}: - {bill.expiration_date} + {formatDate(bill.expiration_date)}

{t("numberOfPassengers")}

- {bill.detail_service.passenger_counts.adults && ( - # {t("adult")}: {bill.detail_service.passenger_counts.adults} + {!!bill.detail_service.passenger_data.adults.count && ( + + {bill.detail_service.passenger_data.adults.names.join(", ")} ( + {t("adult")}) + )}
- {bill.detail_service.passenger_counts.children && ( - # {t("children")}: {bill.detail_service.passenger_counts.children} + {!!bill.detail_service.passenger_data.children.count && ( + + {bill.detail_service.passenger_data.children.names.join(", ")} ( + {t("child")}) + )}
- {bill.detail_service.passenger_counts.infants && ( - # {t("infant")}: {bill.detail_service.passenger_counts.infants} + {!!bill.detail_service.passenger_data.infants.count && ( + + {bill.detail_service.passenger_data.infants.names.join(", ")} ( + {t("infant")}) + )}
@@ -162,7 +242,9 @@ const BillDetailCard: React.FC = ({ bill }) => {

{t("accountNumber")}

- {bill.card_number} + + {bill.card_number} +
@@ -177,8 +259,12 @@ const BillDetailCard: React.FC = ({ bill }) => { />
{bill.uploadedImage.name} - {bill.uploadedImage.size} - + + {bill.uploadedImage.size} + +
) : ( @@ -186,33 +272,48 @@ const BillDetailCard: React.FC = ({ bill }) => { -
- +
+
+ + {(bill.transaction_receipt || uploadedFile) && ( + + )} +
{loadingUpload &&

{t("loading")}

} - {bill.transaction_receipt ? ( - - {t("currentReceipt")} - - ) : ( - - {t("noFileSelected")} - - )} +
+ {bill.transaction_receipt || uploadedFile ? ( + + {t("currentReceipt")} + + ) : ( +
+ +

{t("uploadPassword")}

+
+ )} +
)}
= ({ bill }) => { ); }; -export default BillDetailCard; \ No newline at end of file +export default BillDetailCard; diff --git a/src/app/[locale]/(account-pages)/bills/page.tsx b/src/app/[locale]/(account-pages)/bills/page.tsx index 3d2571f..cdd3f37 100644 --- a/src/app/[locale]/(account-pages)/bills/page.tsx +++ b/src/app/[locale]/(account-pages)/bills/page.tsx @@ -83,7 +83,7 @@ const BillsPage: React.FC = () => { - +
) : bills.length > 0 ? ( bills.map((bill, index) => ( diff --git a/src/app/[locale]/(account-pages)/passengers-list/page.tsx b/src/app/[locale]/(account-pages)/passengers-list/page.tsx index bd7d887..e7d680c 100644 --- a/src/app/[locale]/(account-pages)/passengers-list/page.tsx +++ b/src/app/[locale]/(account-pages)/passengers-list/page.tsx @@ -1,269 +1,68 @@ -"use client"; +"use client" import React, { useEffect, useState } from "react"; -import { FC } from "react"; -import ButtonPrimary from "@/shared/ButtonPrimary"; -import Input from "@/shared/Input"; -import FormItem from "@/app/[locale]/add-listing/FormItem"; -import getImageURL from "@/components/api/getImageURL"; +import PassengerTable from "./PassengerTable"; +import { IoPersonAddOutline } from "react-icons/io5"; import axiosInstance from "@/components/api/axios"; -import { useRouter } from "next/navigation"; +import Link from "next/link"; import { useUserContext } from "@/components/contexts/userContext"; -import { toast } from "react-toastify"; +import { useRouter } from "next/navigation"; import { useTranslation } from "react-i18next"; -export interface CommonLayoutProps { - params: { - id: string; - }; -} - -const EditPassenger: FC = ({ params }) => { - const { user } = useUserContext(); - const router = useRouter(); - const { t } = useTranslation("form"); - - const [passenger, setPassenger] = useState({ - name: "", - passport: "", - number: "", - date: "", - image: "", - }); - - const [originalPassenger, setOriginalPassenger] = useState({ - name: "", - passport: "", - number: "", - date: "", - image: "", - }); - - const [loading, setLoading] = useState(false); - - // Fetch passenger data on component mount - useEffect(() => { - if (Object.keys(user).length) { - axiosInstance - .get(`/api/account/passengers/${params.id}/`, { - headers: { - Authorization: `token ${user.token}`, - }, - }) - .then((response) => { - const passengerData = { - name: response.data.fullname, - passport: response.data.passport_number, - date: response.data.birthdate, - number: response.data.phone_number.replace(/\D/g, ""), - image: response.data.passport_image, - }; - setPassenger(passengerData); - setOriginalPassenger(passengerData); // Save original data for comparison - }) - .catch((error) => { - toast.error(error.message || t("errorOccurred")); - }); - } - }, [user, params.id]); - - // Handle file change for uploading passport image - const handleFileChange = async (e: React.ChangeEvent) => { - setLoading(true); - const file = e.target.files?.[0]; - if (file) { - try { - const image = await getImageURL(file); - setPassenger((prev) => ({ ...prev, image: image.url })); - toast.success(t("imageUploaded")); - } catch (error) { - toast.error(t("imageUploadError")); - } finally { - setLoading(false); - } - } - }; - - // Validate form inputs before saving - const validateForm = () => { - let formIsValid = true; - - if (!passenger.name) { - formIsValid = false; - toast.error(t("fullNameRequired")); - } - - if (!passenger.passport) { - formIsValid = false; - toast.error(t("passportRequired")); - } else if (!/^\d+$/.test(passenger.passport)) { - formIsValid = false; - toast.error(t("passportNumeric")); - } - - if (!passenger.date) { - formIsValid = false; - toast.error(t("dobRequired")); - } - - if (!passenger.number) { - formIsValid = false; - toast.error(t("phoneRequired")); - } else if (!/^\d+$/.test(passenger.number)) { - formIsValid = false; - toast.error(t("phoneNumeric")); - } - - if (!passenger.image) { - formIsValid = false; - toast.error(t("passportImageRequired")); - } - - return formIsValid; - }; - // Save updated passenger details - const handleSavePassenger = async () => { - if (!validateForm()) return; +interface data { + birthdate: string; + fullname: string; + id: number; + passport_image: string; + phone_number: string; + passport_number: string; - const updatedFields: Partial<{ - fullname: string; - passport_number: string; - birthdate: string; - phone_number: string; - passport_image: string; - }> = {}; - - // Only include changed fields - if (passenger.name !== originalPassenger.name) { - updatedFields.fullname = passenger.name; - } - if (passenger.passport !== originalPassenger.passport) { - updatedFields.passport_number = passenger.passport; - } - if (passenger.date !== originalPassenger.date) { - updatedFields.birthdate = passenger.date; - } - if (passenger.number !== originalPassenger.number) { - updatedFields.phone_number = passenger.number; - } - if (passenger.image !== originalPassenger.image) { - updatedFields.passport_image = passenger.image; - } +} - if (Object.keys(updatedFields).length === 0) { - toast.info(t("noChanges")); - return; +const PassengersList = () => { +const [passengers , setPassenger ] = useState([]) +const {user} = useUserContext() +const router = useRouter() +const {t} = useTranslation("form") + +useEffect(() => { + if (!Object.keys(user).length) { + router.replace("/signup"); + } +}, [user, router]); + +useEffect(()=>{ + axiosInstance.get("/api/account/passengers/" ,{ + headers :{ + Authorization : `token ${user.token}` } + }) + .then((response)=>{ + setPassenger(response.data.results); - try { - const response = await axiosInstance.patch( - `/api/account/passengers/${params.id}/`, - updatedFields, - { - headers: { - Authorization: `token ${user.token}`, - "Content-Type": "application/json", - }, - } - ); + }).catch((error)=>{ + console.error(error); + + }) +} , []) - if (response.status === 200) { - toast.success(t("detailsUpdated")); - router.push("/passengers-list"); - } - } catch (error) { - toast.error(t("updateFailed")); - } - }; return ( -
-
-
-
-

{t("editPassengerInfo")}

-
-
- - - setPassenger((prev) => ({ ...prev, name: e.target.value })) - } - placeholder={t("enterFullName")} - /> - - - - - setPassenger((prev) => ({ - ...prev, - passport: e.target.value, - })) - } - type="text" - placeholder={t("enterPassportNumber")} - /> - - - - - setPassenger((prev) => ({ ...prev, date: e.target.value })) - } - type="date" - placeholder={t("dobPlaceholder")} - /> - - - - - setPassenger((prev) => ({ - ...prev, - number: e.target.value.replace(/\D/g, ""), - })) - } - type="text" - placeholder={t("enterPhoneNumber")} - /> - - - - - {loading &&

{t("loading")}

} -
-
-
- -
- { - e.preventDefault(); - handleSavePassenger(); - }} - > - {t("saveChanges")} - -
-
-
+
+ {/* Add New Passenger Section */} + + {/* Adjust icon size */} +

{t("addNewPassenger")}

+ + + {/* Passenger Table */} + {passengers.map((item : data)=>( + + + ))}
); }; -export default EditPassenger; +export default PassengersList; \ No newline at end of file diff --git a/src/app/[locale]/(client-components)/(HeroSearchForm2Mobile)/HeroSearchForm2Mobile.tsx b/src/app/[locale]/(client-components)/(HeroSearchForm2Mobile)/HeroSearchForm2Mobile.tsx index e90d7db..0d6e5ae 100644 --- a/src/app/[locale]/(client-components)/(HeroSearchForm2Mobile)/HeroSearchForm2Mobile.tsx +++ b/src/app/[locale]/(client-components)/(HeroSearchForm2Mobile)/HeroSearchForm2Mobile.tsx @@ -10,8 +10,10 @@ import StaySearchForm from "./(stay-search-form)/StaySearchForm"; import CarsSearchForm from "./(car-search-form)/CarsSearchForm"; import FlightSearchForm from "./(flight-search-form)/FlightSearchForm"; import { usePathname, useRouter } from "next/navigation"; +import { useTranslation } from "react-i18next"; const HeroSearchForm2Mobile = () => { + const { t } = useTranslation("navigation"); const [showModal, setShowModal] = useState(false); // FOR RESET ALL DATA WHEN CLICK CLEAR BUTTON @@ -39,10 +41,10 @@ useEffect(()=>{
- Where to? + {t("Where to?")} - Anywhere • Any week • Add guests + {t("Anywhere • Any week • Add guests")}
@@ -93,7 +95,7 @@ useEffect(()=>{
- {/* {["Stay", "Experiences", "Cars", "Flights"].map( + {/* {t(["Stay", "Experiences", "Cars", "Flights"]).map( (item, index) => ( {({ selected }) => ( @@ -149,7 +151,7 @@ useEffect(()=>{ resetIsShowingDialog(); }} > - Clear all + {t("Clear all")} { @@ -169,4 +171,4 @@ useEffect(()=>{ ); }; -export default HeroSearchForm2Mobile; +export default HeroSearchForm2Mobile; \ No newline at end of file diff --git a/src/app/[locale]/(stay-listings)/TabFilters.tsx b/src/app/[locale]/(stay-listings)/TabFilters.tsx index c5a69b2..df5ec1c 100644 --- a/src/app/[locale]/(stay-listings)/TabFilters.tsx +++ b/src/app/[locale]/(stay-listings)/TabFilters.tsx @@ -9,682 +9,117 @@ import ButtonClose from "@/shared/ButtonClose"; import Checkbox from "@/shared/Checkbox"; import Slider from "rc-slider"; import convertNumbThousand from "@/utils/convertNumbThousand"; +import { useTranslation } from "react-i18next"; -// DEMO DATA -const typeOfPaces = [ - { - name: "Entire place", - description: "Have a place to yourself", - }, - { - name: "Private room", - description: "Have your own room and share some common spaces", - }, - { - name: "Hotel room", - description: - "Have a private or shared room in a boutique hotel, hostel, and more", - }, - { - name: "Shared room", - description: "Stay in a shared space, like a common room", - }, -]; - -const moreFilter1 = [ - { name: "Kitchen", defaultChecked: true }, - { name: "Air conditioning", defaultChecked: true }, - { name: "Heating" }, - { name: "Dryer" }, - { name: "Washer" }, - { name: "Wifi" }, - { name: "Indoor fireplace" }, - { name: "Breakfast" }, - { name: "Hair dryer" }, - { name: " Dedicated workspace" }, -]; - -const moreFilter2 = [ - { name: " Free parking on premise" }, - { name: "Hot tub" }, - { name: "Gym" }, - { name: " Pool" }, - { name: " EV charger" }, -]; - -const moreFilter3 = [ - { name: " House" }, - { name: "Bed and breakfast" }, - { name: "Apartment", defaultChecked: true }, - { name: " Boutique hotel" }, - { name: " Bungalow" }, - { name: " Chalet", defaultChecked: true }, - { name: " Condominium", defaultChecked: true }, - { name: " Cottage" }, - { name: " Guest suite" }, - { name: " Guesthouse" }, -]; - -const moreFilter4 = [{ name: " Pets allowed" }, { name: "Smoking allowed" }]; - -const TabFilters = ({data , -onChangeCountry = (item)=>{} - -}) => { +const TabFilters = ({ data, onChangeCountry = (item) => {} }) => { + const { t } = useTranslation("common"); const [isOpenMoreFilter, setisOpenMoreFilter] = useState(false); const [isOpenMoreFilterMobile, setisOpenMoreFilterMobile] = useState(false); const [rangePrices, setRangePrices] = useState([0, 1000]); const [checkedItems, setCheckedItems] = useState({}); -useEffect(()=>{ -onChangeCountry(checkedItems) -} , [checkedItems]) + useEffect(() => { + onChangeCountry(checkedItems); + }, [checkedItems]); - // const closeModalMoreFilter = () => setisOpenMoreFilter(false); const openModalMoreFilter = () => setisOpenMoreFilter(true); - // const closeModalMoreFilterMobile = () => setisOpenMoreFilterMobile(false); const openModalMoreFilterMobile = () => setisOpenMoreFilterMobile(true); -console.log(data); - - const renderXClear = () => { - return ( - - - - - - ); - }; - - const renderTabsTypeOfPlace = () => { - return ( - - {({ open, close }) => ( - <> - - Type of place - - - - -
-
- {data.map((item) => ( -
- { - setCheckedItems((prev) => ({ - ...prev, - [item.name]: checked, - })); - }} - /> -
- ))} -
-
-
-
- - )} -
- ); - }; - - const renderTabsRoomAndBeds = () => { - return ( - - {({ open, close }) => ( - <> - - Rooms of Beds - - - - -
-
- - - -
-
- - Clear - - - Apply - -
-
-
-
- - )} -
- ); - }; - const renderTabsPriceRage = () => { - return ( - - {({ open, close }) => ( - <> - - - {`$${convertNumbThousand( - rangePrices[0] - )} - $${convertNumbThousand(rangePrices[1])}`}{" "} - - {renderXClear()} - - - -
-
-
- Price per day - setRangePrices(e as number[])} + const renderTabsTypeOfPlace = () => ( + + {({ open, close }) => ( + <> + + {t("TypeOfPlace")} + + + + +
+
+ {data.map((item) => ( +
+ { + setCheckedItems((prev) => ({ + ...prev, + [item.name]: checked, + })); + }} />
- -
-
- -
-
- - $ - -
- -
-
-
- -
-
- - $ - -
- -
-
-
-
-
- - Clear - - - Apply - -
+ ))}
-
-
- - )} -
- ); - }; - -// Inside TabFilters component -const renderMoreFilterItem = ( - data: { - name: string; - defaultChecked?: boolean; - }[] -) => { - const list1 = data.filter((_, i) => i < data.length / 2); - const list2 = data.filter((_, i) => i >= data.length / 2); - return ( -
-
- {list1.map((item) => ( - { - setCheckedItems((prev) => ({ - ...prev, - [item.name]: checked, - })); - }} - /> - ))} -
-
- {list2.map((item) => ( - { - setCheckedItems((prev) => ({ - ...prev, - [item.name]: checked, - })); - }} - /> - ))} -
-
+
+ + + + )} + ); -}; - - - const renderTabMoreFilter = () => { - return ( -
-
- More filters (3) - {renderXClear()} -
- - ( + + {({ open, close }) => ( + <> + -
- - - - - {/* This element is to trick the browser into centering the modal contents. */} - - -
-
- - More filters - - - - -
- -
-
-
-

Amenities

-
- {renderMoreFilterItem(moreFilter1)} -
-
-
-

Facilities

-
- {renderMoreFilterItem(moreFilter2)} -
-
-
-

Property type

-
- {renderMoreFilterItem(moreFilter3)} -
-
-
-

House rules

-
- {renderMoreFilterItem(moreFilter4)} -
-
-
-
- -
- - Clear - - - Apply - -
+ {t("Rooms and Beds")} + + + + +
+
+ + +
- -
-
-
-
- ); - }; - - const renderTabMoreFilterMobile = () => { - return ( -
-
- Countries - {renderXClear()} -
+
+ + + + )} + + ); - - ( + + {({ open, close }) => ( + <> + -
- - - - - {/* This element is to trick the browser into centering the modal contents. */} - - -
-
- - More filters - - - - -
- -
-
- {/* ---- */} -
-

Type of place

-
- {renderMoreFilterItem(data)} -
-
- - {/* ---- */} - {/*
-

Range Prices

-
-
-
- setRangePrices(e as number[])} - /> -
- -
-
- -
-
- - $ - -
- -
-
-
- -
-
- - $ - -
- -
-
-
-
-
-
*/} - - {/* ---- */} - {/*
-

Rooms and beds

-
- - - -
-
*/} - - {/* ---- */} - {/*
-

Amenities

-
- {renderMoreFilterItem(moreFilter1)} -
-
*/} - - {/* ---- */} - {/*
-

Facilities

-
- {renderMoreFilterItem(moreFilter2)} -
-
*/} - - {/* ---- */} - {/*
-

Property type

-
- {renderMoreFilterItem(moreFilter3)} -
-
*/} - - {/* ---- */} - {/*
-

House rules

-
- {renderMoreFilterItem(moreFilter4)} -
-
*/} -
-
- -
- - Clear - - - Apply - -
-
-
-
-
-
-
- ); - }; + + {`${t("$")}${convertNumbThousand(rangePrices[0])} - ${t("$")}${convertNumbThousand(rangePrices[1])}`} {" "} + + + + )} + + ); return (
{renderTabsTypeOfPlace()} - {/* {renderTabsPriceRage()} */} - {/* {renderTabsRoomAndBeds()} */} - {/* {renderTabMoreFilter()} */} + {renderTabsRoomAndBeds()} + {renderTabsPriceRage()}
- {renderTabMoreFilterMobile()}
); }; -export default TabFilters; +export default TabFilters; \ No newline at end of file diff --git a/src/app/[locale]/add-listing/[[...stepIndex]]/PageAddListing1.tsx b/src/app/[locale]/add-listing/[[...stepIndex]]/PageAddListing1.tsx index 1c85156..431fd18 100644 --- a/src/app/[locale]/add-listing/[[...stepIndex]]/PageAddListing1.tsx +++ b/src/app/[locale]/add-listing/[[...stepIndex]]/PageAddListing1.tsx @@ -186,7 +186,7 @@ const PageAddListing1: FC = ({ {/* Passport Number Field */} setNewPassenger((prev: any) => ({ @@ -206,13 +206,13 @@ const PageAddListing1: FC = ({
- {ageLabel && ( + {(ageLabel && Passenger.birthdate ) && ( {passengerAgeLable} diff --git a/src/app/[locale]/custom-trip/page.tsx b/src/app/[locale]/custom-trip/page.tsx index 3cda235..b73c77e 100644 --- a/src/app/[locale]/custom-trip/page.tsx +++ b/src/app/[locale]/custom-trip/page.tsx @@ -454,10 +454,10 @@ const CommonLayout: FC = () => { handleDestinationChange( index, "duration", - Math.max(1, Number(e.target.value)) + e.target.value ) } - min="1" + min="0" /> diff --git a/src/app/[locale]/layout.tsx b/src/app/[locale]/layout.tsx index b128f52..e8909ed 100644 --- a/src/app/[locale]/layout.tsx +++ b/src/app/[locale]/layout.tsx @@ -42,9 +42,9 @@ export default function LocaleLayout({ - - + + {children} + +