fix: sửa lỗi hiển thị trên browser của điện thoại
This commit is contained in:
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+42
-42
File diff suppressed because one or more lines are too long
-2
File diff suppressed because one or more lines are too long
+2
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+2
-2
@@ -5,8 +5,8 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||||
<title>Travel Planner</title>
|
<title>Travel Planner</title>
|
||||||
<script type="module" crossorigin src="/assets/index-UWqs1Nt4.js"></script>
|
<script type="module" crossorigin src="/assets/index-DvhesUei.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-I6bJ9cOX.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-i0kJVU1C.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -355,7 +355,7 @@ export const PublicPhotoModal: React.FC<PublicPhotoModalProps> = ({
|
|||||||
if (!isOpen) return null;
|
if (!isOpen) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 z-[5000] flex items-center justify-center p-4">
|
<div className="fixed inset-0 z-[5000] md:flex md:items-center md:justify-center md:p-4">
|
||||||
{/* Backdrop */}
|
{/* Backdrop */}
|
||||||
<div
|
<div
|
||||||
className="absolute inset-0 bg-slate-950/80 backdrop-blur-md animate-in fade-in duration-300"
|
className="absolute inset-0 bg-slate-950/80 backdrop-blur-md animate-in fade-in duration-300"
|
||||||
@@ -363,22 +363,35 @@ export const PublicPhotoModal: React.FC<PublicPhotoModalProps> = ({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Container */}
|
{/* Container */}
|
||||||
<div className="relative w-full max-w-5xl h-[90vh] md:h-[85vh] bg-slate-900 border border-slate-800 rounded-[32px] shadow-2xl overflow-y-auto md:overflow-hidden flex flex-col md:flex-row animate-in zoom-in-95 duration-300 text-slate-100">
|
<div className="fixed inset-0 overflow-y-auto flex flex-col bg-slate-900 text-slate-100 md:relative md:inset-auto md:overflow-hidden md:rounded-[32px] md:shadow-2xl md:border md:border-slate-800 md:w-full md:max-w-5xl md:h-[85vh] md:flex-row animate-in zoom-in-95 duration-300">
|
||||||
|
|
||||||
{/* Close Button Mobile/Desktop */}
|
{/* Close Button Mobile/Desktop */}
|
||||||
<button
|
<button
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
className="fixed md:absolute top-6 right-6 md:top-4 md:right-4 z-50 p-2 bg-slate-950/60 hover:bg-slate-800/80 border border-slate-700/50 rounded-full text-slate-300 hover:text-white transition-colors"
|
className="fixed md:absolute top-[calc(1rem+env(safe-area-inset-top,0px))] right-4 md:top-4 md:right-4 z-50 p-2 bg-slate-950/60 hover:bg-slate-800/80 border border-slate-700/50 rounded-full text-slate-300 hover:text-white transition-colors"
|
||||||
>
|
>
|
||||||
<X className="w-5 h-5" />
|
<X className="w-5 h-5" />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{/* Left Side: Photo Detail */}
|
{/* Left Side: Photo Detail */}
|
||||||
<div className="relative w-full md:w-3/5 h-[45vh] md:h-full bg-slate-950 flex items-center justify-center overflow-hidden group shrink-0">
|
<div className="relative w-full md:w-3/5 md:h-full bg-slate-950 flex flex-col overflow-hidden group shrink-0">
|
||||||
|
|
||||||
|
{/* Photo wrapper for mobile view (handles top overlay name and bottom-right like) */}
|
||||||
|
<div className="relative w-full flex items-center justify-center md:absolute md:inset-0 md:flex md:items-center md:justify-center bg-slate-950">
|
||||||
|
{/* Mobile Only: Uploader details overlay */}
|
||||||
|
<div className="absolute top-[calc(0.75rem+env(safe-area-inset-top,0px))] left-4 z-40 md:hidden flex items-center gap-2 bg-slate-950/70 backdrop-blur-md px-2.5 py-1.5 rounded-full border border-slate-700/50">
|
||||||
|
<div className="w-5 h-5 rounded-full bg-emerald-500/20 flex items-center justify-center">
|
||||||
|
<User className="w-3 h-3 text-emerald-400" />
|
||||||
|
</div>
|
||||||
|
<span className="text-xs text-slate-200 max-w-[120px] truncate">
|
||||||
|
{photo.uploader?.name || 'Ẩn danh'}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Like Button Overlay */}
|
{/* Like Button Overlay */}
|
||||||
<button
|
<button
|
||||||
onClick={handleToggleLike}
|
onClick={handleToggleLike}
|
||||||
className="absolute top-4 left-4 z-40 flex items-center gap-1.5 bg-slate-950/70 hover:bg-slate-900/80 border border-slate-700/50 text-slate-200 hover:text-white font-bold py-1.5 px-3 rounded-full transition-all active:scale-95 text-[11px] backdrop-blur-md"
|
className="absolute bottom-4 right-4 z-40 flex items-center gap-1.5 bg-slate-950/70 hover:bg-slate-900/80 border border-slate-700/50 text-slate-200 hover:text-white font-bold py-1.5 px-3 rounded-full transition-all active:scale-95 text-[11px] backdrop-blur-md md:absolute md:top-[calc(1rem+env(safe-area-inset-top,0px))] md:left-4 md:bottom-auto md:right-auto"
|
||||||
title={isLiked ? "Bỏ thích" : "Thích"}
|
title={isLiked ? "Bỏ thích" : "Thích"}
|
||||||
>
|
>
|
||||||
<Heart className={`w-4 h-4 transition-colors ${
|
<Heart className={`w-4 h-4 transition-colors ${
|
||||||
@@ -390,11 +403,13 @@ export const PublicPhotoModal: React.FC<PublicPhotoModalProps> = ({
|
|||||||
<img
|
<img
|
||||||
src={photo.imageUrl}
|
src={photo.imageUrl}
|
||||||
alt="Public Map Upload"
|
alt="Public Map Upload"
|
||||||
className="w-full h-full object-contain cursor-zoom-in"
|
className="w-full h-auto max-h-[85vh] object-contain cursor-zoom-in md:h-full md:max-h-none"
|
||||||
onClick={() => setIsFullscreen(true)}
|
onClick={() => setIsFullscreen(true)}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Info & Timeline overlay inside photo panel */}
|
{/* Info & Timeline overlay inside photo panel */}
|
||||||
<div className="absolute bottom-0 left-0 right-0 p-6 bg-gradient-to-t from-black/60 via-black/20 to-transparent flex flex-col gap-4">
|
<div className="relative p-6 bg-slate-900 border-b border-slate-800/60 md:absolute md:bottom-0 md:left-0 md:right-0 md:bg-gradient-to-t md:from-black/60 md:via-black/20 md:to-transparent md:border-b-0 flex flex-col gap-4">
|
||||||
|
|
||||||
{/* Timeline scroll */}
|
{/* Timeline scroll */}
|
||||||
{photoGroup && photoGroup.length > 1 && (
|
{photoGroup && photoGroup.length > 1 && (
|
||||||
@@ -437,7 +452,7 @@ export const PublicPhotoModal: React.FC<PublicPhotoModalProps> = ({
|
|||||||
value={editTitle}
|
value={editTitle}
|
||||||
onChange={(e) => setEditTitle(e.target.value)}
|
onChange={(e) => setEditTitle(e.target.value)}
|
||||||
placeholder="Nhập tiêu đề cho ảnh..."
|
placeholder="Nhập tiêu đề cho ảnh..."
|
||||||
className="w-full bg-slate-850 border border-slate-700/60 text-slate-100 rounded-xl px-3 py-2 text-xs focus:outline-none focus:ring-1 focus:ring-emerald-500"
|
className="w-full bg-slate-850 border border-slate-700/60 text-slate-100 rounded-xl px-3 py-2 text-base md:text-xs focus:outline-none focus:ring-1 focus:ring-emerald-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -448,7 +463,7 @@ export const PublicPhotoModal: React.FC<PublicPhotoModalProps> = ({
|
|||||||
onChange={(e) => setEditDescription(e.target.value)}
|
onChange={(e) => setEditDescription(e.target.value)}
|
||||||
placeholder="Mô tả bức ảnh này..."
|
placeholder="Mô tả bức ảnh này..."
|
||||||
rows={2}
|
rows={2}
|
||||||
className="w-full bg-slate-850 border border-slate-700/60 text-slate-100 rounded-xl px-3 py-2 text-xs focus:outline-none focus:ring-1 focus:ring-emerald-500 resize-none"
|
className="w-full bg-slate-850 border border-slate-700/60 text-slate-100 rounded-xl px-3 py-2 text-base md:text-xs focus:outline-none focus:ring-1 focus:ring-emerald-500 resize-none"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -461,7 +476,7 @@ export const PublicPhotoModal: React.FC<PublicPhotoModalProps> = ({
|
|||||||
value={editLat}
|
value={editLat}
|
||||||
onChange={(e) => setEditLat(e.target.value === '' ? '' : parseFloat(e.target.value))}
|
onChange={(e) => setEditLat(e.target.value === '' ? '' : parseFloat(e.target.value))}
|
||||||
placeholder="Vĩ độ..."
|
placeholder="Vĩ độ..."
|
||||||
className="w-full bg-slate-850 border border-slate-700/60 text-slate-100 rounded-xl px-3 py-2 text-xs focus:outline-none focus:ring-1 focus:ring-emerald-500"
|
className="w-full bg-slate-850 border border-slate-700/60 text-slate-100 rounded-xl px-3 py-2 text-base md:text-xs focus:outline-none focus:ring-1 focus:ring-emerald-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -472,7 +487,7 @@ export const PublicPhotoModal: React.FC<PublicPhotoModalProps> = ({
|
|||||||
value={editLng}
|
value={editLng}
|
||||||
onChange={(e) => setEditLng(e.target.value === '' ? '' : parseFloat(e.target.value))}
|
onChange={(e) => setEditLng(e.target.value === '' ? '' : parseFloat(e.target.value))}
|
||||||
placeholder="Kinh độ..."
|
placeholder="Kinh độ..."
|
||||||
className="w-full bg-slate-850 border border-slate-700/60 text-slate-100 rounded-xl px-3 py-2 text-xs focus:outline-none focus:ring-1 focus:ring-emerald-500"
|
className="w-full bg-slate-850 border border-slate-700/60 text-slate-100 rounded-xl px-3 py-2 text-base md:text-xs focus:outline-none focus:ring-1 focus:ring-emerald-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -561,7 +576,7 @@ export const PublicPhotoModal: React.FC<PublicPhotoModalProps> = ({
|
|||||||
<MapPin className="w-3.5 h-3.5 text-rose-500" />
|
<MapPin className="w-3.5 h-3.5 text-rose-500" />
|
||||||
Địa điểm: {resolvedAddress}
|
Địa điểm: {resolvedAddress}
|
||||||
</div>
|
</div>
|
||||||
<div className="hidden md:flex items-center gap-1.5 font-semibold text-emerald-400">
|
<div className="hidden md:flex items-center gap-1.5 text-xs text-emerald-400">
|
||||||
<User className="w-3.5 h-3.5" />
|
<User className="w-3.5 h-3.5" />
|
||||||
Người đăng: {photo.uploader?.name || 'Ẩn danh'}
|
Người đăng: {photo.uploader?.name || 'Ẩn danh'}
|
||||||
</div>
|
</div>
|
||||||
@@ -572,7 +587,7 @@ export const PublicPhotoModal: React.FC<PublicPhotoModalProps> = ({
|
|||||||
download
|
download
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="hidden md:flex items-center gap-1.5 bg-slate-800/80 hover:bg-slate-700/80 border border-slate-700/50 text-slate-200 hover:text-white font-bold py-1 px-3 rounded-full transition-all active:scale-95 text-[10px]"
|
className="flex items-center gap-1.5 bg-slate-800/80 hover:bg-slate-700/80 border border-slate-700/50 text-slate-200 hover:text-white font-bold py-1 px-3 rounded-full transition-all active:scale-95 text-[10px]"
|
||||||
>
|
>
|
||||||
<Download className="w-3.5 h-3.5 text-emerald-500" />
|
<Download className="w-3.5 h-3.5 text-emerald-500" />
|
||||||
Tải ảnh gốc
|
Tải ảnh gốc
|
||||||
@@ -594,39 +609,11 @@ export const PublicPhotoModal: React.FC<PublicPhotoModalProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Mobile Only: Uploader details & divider */}
|
|
||||||
<div className="block md:hidden p-6 bg-slate-900 border-t border-slate-800/60 space-y-4 shrink-0">
|
|
||||||
<div className="flex items-center justify-between gap-4">
|
|
||||||
<div className="flex items-center gap-2.5 text-left">
|
|
||||||
<div className="p-2.5 bg-emerald-500/10 rounded-xl text-emerald-400">
|
|
||||||
<User className="w-5 h-5" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span className="text-[10px] text-slate-450 block uppercase font-bold tracking-wider">Người đăng ảnh</span>
|
|
||||||
<span className="text-sm font-semibold text-white">{photo.uploader?.name || 'Ẩn danh'}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{isAuthorized && photo.originalUrl && (
|
|
||||||
<a
|
|
||||||
href={photo.originalUrl}
|
|
||||||
download
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="flex items-center gap-1.5 bg-slate-850 hover:bg-slate-800 border border-slate-700 text-slate-200 hover:text-white font-bold py-2 px-4 rounded-xl transition-all text-xs"
|
|
||||||
>
|
|
||||||
<Download className="w-4 h-4 text-emerald-500" />
|
|
||||||
Tải ảnh gốc
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="border-t border-slate-800/60 pt-2" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Right Side: Comments */}
|
{/* Right Side: Comments */}
|
||||||
<div className="w-full md:w-2/5 h-auto md:h-full flex flex-col bg-slate-900 border-t md:border-t-0 md:border-l border-slate-800">
|
<div className="w-full md:w-2/5 md:flex-1 md:min-h-0 flex flex-col bg-slate-900 border-t md:border-t-0 md:border-l border-slate-800">
|
||||||
|
|
||||||
{/* Comments Header */}
|
{/* Comments Header */}
|
||||||
<div className="p-6 border-b border-slate-800 flex items-center justify-between">
|
<div className="hidden md:block p-6 border-b border-slate-800">
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-lg font-black tracking-tight text-white flex items-center gap-2">
|
<h3 className="text-lg font-black tracking-tight text-white flex items-center gap-2">
|
||||||
<MessageSquare className="w-5 h-5 text-emerald-500" />
|
<MessageSquare className="w-5 h-5 text-emerald-500" />
|
||||||
@@ -637,7 +624,7 @@ export const PublicPhotoModal: React.FC<PublicPhotoModalProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Comments list scroll area */}
|
{/* Comments list scroll area */}
|
||||||
<div className="flex-1 overflow-y-auto p-6 space-y-4 bg-slate-900/50">
|
<div className="md:flex-1 md:overflow-y-auto p-6 space-y-4 bg-slate-900/50">
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<div className="flex flex-col items-center justify-center py-12 text-slate-500 gap-2">
|
<div className="flex flex-col items-center justify-center py-12 text-slate-500 gap-2">
|
||||||
<Loader2 className="w-8 h-8 animate-spin text-emerald-500" />
|
<Loader2 className="w-8 h-8 animate-spin text-emerald-500" />
|
||||||
@@ -676,7 +663,7 @@ export const PublicPhotoModal: React.FC<PublicPhotoModalProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Comment Input Area */}
|
{/* Comment Input Area */}
|
||||||
<div className="p-4 bg-slate-950/40 border-t border-slate-800/80">
|
<div className="sticky bottom-0 md:static p-4 bg-slate-950 md:bg-slate-950/40 border-t border-slate-800/80 pb-[calc(1rem+env(safe-area-inset-bottom,0px))] md:pb-4 z-40">
|
||||||
<div className="relative flex items-center gap-2">
|
<div className="relative flex items-center gap-2">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@@ -684,7 +671,7 @@ export const PublicPhotoModal: React.FC<PublicPhotoModalProps> = ({
|
|||||||
onChange={(e) => setNewComment(e.target.value)}
|
onChange={(e) => setNewComment(e.target.value)}
|
||||||
onKeyDown={(e) => e.key === 'Enter' && !isSending && handleSend()}
|
onKeyDown={(e) => e.key === 'Enter' && !isSending && handleSend()}
|
||||||
placeholder="Viết bình luận công khai..."
|
placeholder="Viết bình luận công khai..."
|
||||||
className="flex-1 bg-slate-800/65 border border-slate-700/70 text-slate-100 placeholder-slate-500 rounded-2xl px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-emerald-500 focus:border-transparent transition-all"
|
className="flex-1 bg-slate-800/65 border border-slate-700/70 text-slate-100 placeholder-slate-500 rounded-2xl px-4 py-3 text-base md:text-sm focus:outline-none focus:ring-2 focus:ring-emerald-500 focus:border-transparent transition-all"
|
||||||
disabled={isSending}
|
disabled={isSending}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -94,6 +94,14 @@ export const ExploreMap = ({ onBack, onLogout, user, onViewTour, onOpenMyPhotos,
|
|||||||
groups[key].push(photo);
|
groups[key].push(photo);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// Sort each group by likes descending
|
||||||
|
Object.values(groups).forEach((group) => {
|
||||||
|
group.sort((a, b) => {
|
||||||
|
const likesA = a.metadata?.likedUserIds?.length || 0;
|
||||||
|
const likesB = b.metadata?.likedUserIds?.length || 0;
|
||||||
|
return likesB - likesA;
|
||||||
|
});
|
||||||
|
});
|
||||||
return Object.values(groups);
|
return Object.values(groups);
|
||||||
}, [publicPhotos]);
|
}, [publicPhotos]);
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,12 @@ export const LandingPage: React.FC<LandingPageProps> = ({ onContinue, onGoToSign
|
|||||||
const res = await fetch('/api/v1/public-photos');
|
const res = await fetch('/api/v1/public-photos');
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
setPublicPhotos(data);
|
const sortedData = data.sort((a: any, b: any) => {
|
||||||
|
const likesA = a.metadata?.likedUserIds?.length || 0;
|
||||||
|
const likesB = b.metadata?.likedUserIds?.length || 0;
|
||||||
|
return likesB - likesA;
|
||||||
|
});
|
||||||
|
setPublicPhotos(sortedData);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Lỗi khi tải ảnh công khai:', e);
|
console.error('Lỗi khi tải ảnh công khai:', e);
|
||||||
|
|||||||
@@ -4,6 +4,15 @@ import { useNotification } from '@/hooks/useNotification';
|
|||||||
import { useConfirm } from '@/hooks/useConfirm';
|
import { useConfirm } from '@/hooks/useConfirm';
|
||||||
import { CoordinateSelectModal } from '../components/CoordinateSelectModal';
|
import { CoordinateSelectModal } from '../components/CoordinateSelectModal';
|
||||||
|
|
||||||
|
const getMostLikedPhoto = (photos: any[]) => {
|
||||||
|
if (!photos || photos.length === 0) return null;
|
||||||
|
return [...photos].sort((a, b) => {
|
||||||
|
const likesA = a.metadata?.likedUserIds?.length || 0;
|
||||||
|
const likesB = b.metadata?.likedUserIds?.length || 0;
|
||||||
|
return likesB - likesA;
|
||||||
|
})[0];
|
||||||
|
};
|
||||||
|
|
||||||
export const MyPhotosPage = ({ onBack }: { onBack: () => void }) => {
|
export const MyPhotosPage = ({ onBack }: { onBack: () => void }) => {
|
||||||
const [photos, setPhotos] = useState<any[]>([]);
|
const [photos, setPhotos] = useState<any[]>([]);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
@@ -195,7 +204,7 @@ export const MyPhotosPage = ({ onBack }: { onBack: () => void }) => {
|
|||||||
// Effect để thiết lập ảnh được chọn hiển thị hoặc reset nếu ảnh hiện tại không còn trong danh sách lọc
|
// Effect để thiết lập ảnh được chọn hiển thị hoặc reset nếu ảnh hiện tại không còn trong danh sách lọc
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (filteredPhotos.length > 0 && (!selectedPhotoForDisplay || !filteredPhotos.some(p => p.id === selectedPhotoForDisplay.id))) {
|
if (filteredPhotos.length > 0 && (!selectedPhotoForDisplay || !filteredPhotos.some(p => p.id === selectedPhotoForDisplay.id))) {
|
||||||
setSelectedPhotoForDisplay(filteredPhotos[0]);
|
setSelectedPhotoForDisplay(getMostLikedPhoto(filteredPhotos));
|
||||||
} else if (filteredPhotos.length === 0) {
|
} else if (filteredPhotos.length === 0) {
|
||||||
setSelectedPhotoForDisplay(null);
|
setSelectedPhotoForDisplay(null);
|
||||||
} else if (selectedPhotoForDisplay) {
|
} else if (selectedPhotoForDisplay) {
|
||||||
|
|||||||
@@ -329,6 +329,15 @@ const MapContextMenu = ({ onAction }: { onAction: (action: string, latlng: L.Lat
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getMostLikedPhoto = (photos: any[]) => {
|
||||||
|
if (!photos || photos.length === 0) return null;
|
||||||
|
return [...photos].sort((a, b) => {
|
||||||
|
const likesA = a.metadata?.likedUserIds?.length || 0;
|
||||||
|
const likesB = b.metadata?.likedUserIds?.length || 0;
|
||||||
|
return likesB - likesA;
|
||||||
|
})[0];
|
||||||
|
};
|
||||||
|
|
||||||
export const TourDetailPage = ({
|
export const TourDetailPage = ({
|
||||||
onBack,
|
onBack,
|
||||||
tourId,
|
tourId,
|
||||||
@@ -682,9 +691,9 @@ export const TourDetailPage = ({
|
|||||||
// Effect to set initial selected photo for display or reset if current one is no longer in filtered list
|
// Effect to set initial selected photo for display or reset if current one is no longer in filtered list
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (filteredPhotos.length > 0 && !selectedPhotoForDisplay) {
|
if (filteredPhotos.length > 0 && !selectedPhotoForDisplay) {
|
||||||
setSelectedPhotoForDisplay(filteredPhotos[0]);
|
setSelectedPhotoForDisplay(getMostLikedPhoto(filteredPhotos));
|
||||||
} else if (selectedPhotoForDisplay && !filteredPhotos.some(p => p.id === selectedPhotoForDisplay.id)) {
|
} else if (selectedPhotoForDisplay && !filteredPhotos.some(p => p.id === selectedPhotoForDisplay.id)) {
|
||||||
setSelectedPhotoForDisplay(filteredPhotos.length > 0 ? filteredPhotos[0] : null);
|
setSelectedPhotoForDisplay(filteredPhotos.length > 0 ? getMostLikedPhoto(filteredPhotos) : null);
|
||||||
}
|
}
|
||||||
}, [filteredPhotos, selectedPhotoForDisplay]);
|
}, [filteredPhotos, selectedPhotoForDisplay]);
|
||||||
const [isCommentModalOpen, setIsCommentModalOpen] = useState(false);
|
const [isCommentModalOpen, setIsCommentModalOpen] = useState(false);
|
||||||
@@ -835,7 +844,7 @@ export const TourDetailPage = ({
|
|||||||
if (currentTour && currentTour.photos && currentTour.photos.length > 0) {
|
if (currentTour && currentTour.photos && currentTour.photos.length > 0) {
|
||||||
// If there are photos, and no leg is selected, default to 'all' and first photo
|
// If there are photos, and no leg is selected, default to 'all' and first photo
|
||||||
if (selectedLegIdForPhoto === 'all' && !selectedPhotoForDisplay) {
|
if (selectedLegIdForPhoto === 'all' && !selectedPhotoForDisplay) {
|
||||||
setSelectedPhotoForDisplay(currentTour.photos[0]);
|
setSelectedPhotoForDisplay(getMostLikedPhoto(currentTour.photos));
|
||||||
} else if (selectedLegIdForPhoto !== 'all') {
|
} else if (selectedLegIdForPhoto !== 'all') {
|
||||||
// If a specific leg is selected, try to find a photo for that leg
|
// If a specific leg is selected, try to find a photo for that leg
|
||||||
const targetLeg = legs.find(l => l.id === selectedLegIdForPhoto);
|
const targetLeg = legs.find(l => l.id === selectedLegIdForPhoto);
|
||||||
@@ -843,9 +852,9 @@ export const TourDetailPage = ({
|
|||||||
const locationIdsInLeg = targetLeg.locations.map((loc: any) => loc.id);
|
const locationIdsInLeg = targetLeg.locations.map((loc: any) => loc.id);
|
||||||
const photosInLeg = currentTour.photos.filter((p: any) => p.locationId && locationIdsInLeg.includes(p.locationId));
|
const photosInLeg = currentTour.photos.filter((p: any) => p.locationId && locationIdsInLeg.includes(p.locationId));
|
||||||
if (photosInLeg.length > 0 && !selectedPhotoForDisplay) {
|
if (photosInLeg.length > 0 && !selectedPhotoForDisplay) {
|
||||||
setSelectedPhotoForDisplay(photosInLeg[0]);
|
setSelectedPhotoForDisplay(getMostLikedPhoto(photosInLeg));
|
||||||
} else if (selectedPhotoForDisplay && !photosInLeg.some(p => p.id === selectedPhotoForDisplay.id)) {
|
} else if (selectedPhotoForDisplay && !photosInLeg.some(p => p.id === selectedPhotoForDisplay.id)) {
|
||||||
setSelectedPhotoForDisplay(photosInLeg.length > 0 ? photosInLeg[0] : null);
|
setSelectedPhotoForDisplay(photosInLeg.length > 0 ? getMostLikedPhoto(photosInLeg) : null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1345,7 +1354,7 @@ export const TourDetailPage = ({
|
|||||||
date: tourDateDisplay,
|
date: tourDateDisplay,
|
||||||
membersCount: currentTour?.participants?.length || 0,
|
membersCount: currentTour?.participants?.length || 0,
|
||||||
budget: currentTour?.totalCost ? `${Number(currentTour.totalCost).toLocaleString()} VND` : "0 VND",
|
budget: currentTour?.totalCost ? `${Number(currentTour.totalCost).toLocaleString()} VND` : "0 VND",
|
||||||
coverImage: currentTour?.photos?.[0]?.imageUrl || "https://images.unsplash.com/photo-1476514525535-07fb3b4ae5f1?q=80&w=2070&auto=format&fit=crop"
|
coverImage: getMostLikedPhoto(currentTour?.photos || [])?.imageUrl || "https://images.unsplash.com/photo-1476514525535-07fb3b4ae5f1?q=80&w=2070&auto=format&fit=crop"
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user