feat: cập nhật giao diện tour hiển thị mô tả trên banner
This commit is contained in:
@@ -178,6 +178,8 @@ export const TourDetailPage = ({ onBack }: { onBack: () => void }) => {
|
|||||||
const [selectedMember, setSelectedMember] = useState<any>(null);
|
const [selectedMember, setSelectedMember] = useState<any>(null);
|
||||||
const [isMemberDetailOpen, setIsMemberDetailOpen] = useState(false);
|
const [isMemberDetailOpen, setIsMemberDetailOpen] = useState(false);
|
||||||
const [joinRequests, setJoinRequests] = useState<any[]>([]);
|
const [joinRequests, setJoinRequests] = useState<any[]>([]);
|
||||||
|
const [titleInput, setTitleInput] = useState(currentTour?.title ?? '');
|
||||||
|
const [descriptionInput, setDescriptionInput] = useState(currentTour?.description ?? '');
|
||||||
// State cho input số lượng người tham gia
|
// State cho input số lượng người tham gia
|
||||||
const [adultCountInput, setAdultCountInput] = useState(currentTour?.adultCount ?? 0);
|
const [adultCountInput, setAdultCountInput] = useState(currentTour?.adultCount ?? 0);
|
||||||
const [childCountInput, setChildCountInput] = useState(currentTour?.childCount ?? 0);
|
const [childCountInput, setChildCountInput] = useState(currentTour?.childCount ?? 0);
|
||||||
@@ -340,18 +342,20 @@ export const TourDetailPage = ({ onBack }: { onBack: () => void }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Hàm xử lý cập nhật số lượng người tham gia
|
// Hàm xử lý cập nhật số lượng người tham gia
|
||||||
const handleUpdateParticipantCounts = async () => {
|
const handleUpdateTourInfo = async () => {
|
||||||
if (!currentTour) return;
|
if (!currentTour) return;
|
||||||
try {
|
try {
|
||||||
await updateTourDetails(currentTour.id, {
|
await updateTourDetails(currentTour.id, {
|
||||||
|
title: titleInput,
|
||||||
|
description: descriptionInput,
|
||||||
adultCount: adultCountInput,
|
adultCount: adultCountInput,
|
||||||
childCount: childCountInput,
|
childCount: childCountInput,
|
||||||
childDiscount: childDiscountInput,
|
childDiscount: childDiscountInput,
|
||||||
});
|
});
|
||||||
notificationModal.openModal('Thành công', 'Đã cập nhật số lượng người tham gia.', 'success');
|
notificationModal.openModal('Thành công', 'Đã cập nhật thông tin chuyến đi.', 'success');
|
||||||
fetchTour(currentTour.id); // Re-fetch tour để cập nhật lại các tính toán liên quan
|
fetchTour(currentTour.id); // Re-fetch tour để cập nhật lại các tính toán liên quan
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
notificationModal.openModal('Lỗi', error.message || 'Không thể cập nhật số lượng người tham gia.', 'error');
|
notificationModal.openModal('Lỗi', error.message || 'Không thể cập nhật thông tin.', 'error');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Xác định Điểm xuất phát và Điểm kết thúc hiển thị dưới widget tài chính
|
// Xác định Điểm xuất phát và Điểm kết thúc hiển thị dưới widget tài chính
|
||||||
@@ -428,6 +432,14 @@ export const TourDetailPage = ({ onBack }: { onBack: () => void }) => {
|
|||||||
<div className="relative z-10 p-6 text-white pt-28 pb-20">
|
<div className="relative z-10 p-6 text-white pt-28 pb-20">
|
||||||
<div className="max-w-2xl mx-auto space-y-4">
|
<div className="max-w-2xl mx-auto space-y-4">
|
||||||
<h2 className="text-3xl font-black tracking-tight drop-shadow-md">{tourInfo.title}</h2>
|
<h2 className="text-3xl font-black tracking-tight drop-shadow-md">{tourInfo.title}</h2>
|
||||||
|
|
||||||
|
{currentTour?.description && (
|
||||||
|
<p className="text-sm md:text-base text-white/90 max-w-xl line-clamp-3 md:line-clamp-none bg-black/20 backdrop-blur-sm p-4 rounded-2xl border border-white/10 italic leading-relaxed">
|
||||||
|
<Quote className="w-4 h-4 inline-block mr-2 opacity-50" />
|
||||||
|
{currentTour.description}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Dòng tóm tắt Lộ trình */}
|
{/* Dòng tóm tắt Lộ trình */}
|
||||||
<div className="mt-3 text-[11px] sm:text-sm font-bold text-white bg-black/40 backdrop-blur-md px-4 py-2 rounded-xl border border-white/10 inline-flex items-center max-w-full">
|
<div className="mt-3 text-[11px] sm:text-sm font-bold text-white bg-black/40 backdrop-blur-md px-4 py-2 rounded-xl border border-white/10 inline-flex items-center max-w-full">
|
||||||
<span className="text-white/60 mr-1">Lộ trình:</span>
|
<span className="text-white/60 mr-1">Lộ trình:</span>
|
||||||
@@ -819,13 +831,43 @@ export const TourDetailPage = ({ onBack }: { onBack: () => void }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{canEdit && ( // Chỉ OWNER và MANAGER mới có thể chỉnh sửa phần này
|
{canEdit && (
|
||||||
<div className="p-6 bg-white rounded-3xl border border-gray-100 shadow-sm animate-in zoom-in-95">
|
<div className="p-6 bg-white rounded-3xl border border-gray-100 shadow-sm animate-in zoom-in-95">
|
||||||
|
<div className="flex items-center gap-3 mb-6">
|
||||||
|
<Settings className="w-6 h-6 text-blue-500" />
|
||||||
|
<h3 className="text-lg font-bold text-gray-900">Thông tin cơ bản</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-4 mb-8">
|
||||||
|
{isOwner && (
|
||||||
|
<>
|
||||||
|
<div>
|
||||||
|
<label className="block text-xs font-black text-gray-400 uppercase tracking-widest mb-2 ml-1">Tiêu đề Tour</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={titleInput}
|
||||||
|
onChange={(e) => setTitleInput(e.target.value)}
|
||||||
|
className="w-full px-4 py-3 bg-gray-50 border border-gray-100 rounded-2xl focus:ring-2 focus:ring-blue-500 outline-none transition-all text-sm font-bold"
|
||||||
|
placeholder="Nhập tên chuyến đi..."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block text-xs font-black text-gray-400 uppercase tracking-widest mb-2 ml-1">Mô tả chuyến đi</label>
|
||||||
|
<textarea
|
||||||
|
value={descriptionInput}
|
||||||
|
onChange={(e) => setDescriptionInput(e.target.value)}
|
||||||
|
className="w-full px-4 py-3 bg-gray-50 border border-gray-100 rounded-2xl focus:ring-2 focus:ring-blue-500 outline-none transition-all text-sm min-h-[100px] resize-none"
|
||||||
|
placeholder="Viết vài dòng giới thiệu về hành trình này..."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="flex items-center gap-3 mb-4">
|
<div className="flex items-center gap-3 mb-4">
|
||||||
<Users className="w-6 h-6 text-purple-500" />
|
<Users className="w-6 h-6 text-purple-500" />
|
||||||
<h3 className="text-lg font-bold text-gray-900">Quản lý số lượng người tham gia</h3>
|
<h3 className="text-md font-bold text-gray-800">Số lượng người tham gia</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-4">
|
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="adultCount" className="block text-sm font-medium text-gray-700 mb-1">Số lượng người lớn</label>
|
<label htmlFor="adultCount" className="block text-sm font-medium text-gray-700 mb-1">Số lượng người lớn</label>
|
||||||
<input
|
<input
|
||||||
@@ -860,9 +902,10 @@ export const TourDetailPage = ({ onBack }: { onBack: () => void }) => {
|
|||||||
className="w-full px-4 py-2 border border-gray-200 rounded-xl focus:ring-blue-500 focus:border-blue-500"
|
className="w-full px-4 py-2 border border-gray-200 rounded-xl focus:ring-blue-500 focus:border-blue-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={handleUpdateParticipantCounts}
|
onClick={handleUpdateTourInfo}
|
||||||
className="w-full px-4 py-3 bg-blue-600 hover:bg-blue-700 text-white font-bold rounded-xl transition-all shadow-md"
|
className="w-full mt-6 px-4 py-4 bg-blue-600 hover:bg-blue-700 text-white font-black uppercase tracking-widest rounded-2xl transition-all shadow-lg shadow-blue-100 active:scale-95"
|
||||||
>
|
>
|
||||||
Lưu thay đổi
|
Lưu thay đổi
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user