fix: cho phép người đã tải ảnh lên được quyền chỉnh sửa
This commit is contained in:
@@ -504,7 +504,7 @@ export const TourDetailPage = ({
|
||||
const [isMemberDetailOpen, setIsMemberDetailOpen] = useState(false);
|
||||
const [selectedPhotoForDisplay, setSelectedPhotoForDisplay] = useState<any | null>(null); // New state for large photo display
|
||||
const currentUserId = useMemo(() => {
|
||||
const token = localStorage.getItem('token');
|
||||
const token = localStorage.getItem('token') || localStorage.getItem('guest_token');
|
||||
if (!token) return null;
|
||||
try {
|
||||
return JSON.parse(atob(token.split('.')[1])).sub;
|
||||
@@ -514,7 +514,7 @@ export const TourDetailPage = ({
|
||||
}, []);
|
||||
|
||||
const currentUser = useMemo(() => {
|
||||
const userStr = localStorage.getItem('user');
|
||||
const userStr = localStorage.getItem('user') || localStorage.getItem('guest_user');
|
||||
if (!userStr) return null;
|
||||
try {
|
||||
return JSON.parse(userStr);
|
||||
@@ -531,6 +531,7 @@ export const TourDetailPage = ({
|
||||
const [isSavingPhotoEdit, setIsSavingPhotoEdit] = useState(false);
|
||||
const [isMapOpen, setIsMapOpen] = useState(false);
|
||||
const [resolvedAddress, setResolvedAddress] = useState<string>('');
|
||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||
|
||||
const likedUserIds = selectedPhotoForDisplay && selectedPhotoForDisplay.metadata && Array.isArray(selectedPhotoForDisplay.metadata.likedUserIds)
|
||||
? selectedPhotoForDisplay.metadata.likedUserIds
|
||||
@@ -544,7 +545,7 @@ export const TourDetailPage = ({
|
||||
const response = await fetch(`/api/v1/photos/${selectedPhotoForDisplay.id}/toggle-like`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${localStorage.getItem('token')}`
|
||||
'Authorization': `Bearer ${localStorage.getItem('token') || localStorage.getItem('guest_token')}`
|
||||
}
|
||||
});
|
||||
if (response.ok) {
|
||||
@@ -621,7 +622,7 @@ export const TourDetailPage = ({
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${localStorage.getItem('token')}`
|
||||
'Authorization': `Bearer ${localStorage.getItem('token') || localStorage.getItem('guest_token')}`
|
||||
},
|
||||
body: JSON.stringify({
|
||||
title: editPhotoTitle,
|
||||
@@ -735,7 +736,7 @@ export const TourDetailPage = ({
|
||||
const response = await fetch(`/api/v1/photos/${photoId}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${localStorage.getItem('token')}`
|
||||
'Authorization': `Bearer ${localStorage.getItem('token') || localStorage.getItem('guest_token')}`
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2057,7 +2058,8 @@ export const TourDetailPage = ({
|
||||
<img
|
||||
src={selectedPhotoForDisplay.imageUrl}
|
||||
alt="Selected Tour Photo"
|
||||
className="max-w-full max-h-[calc(100vh-350px)] object-contain"
|
||||
className="max-w-full max-h-[calc(100vh-350px)] object-contain cursor-zoom-in"
|
||||
onClick={() => setIsFullscreen(true)}
|
||||
/>
|
||||
|
||||
{/* Overlays (Only show when not editing) */}
|
||||
@@ -2076,7 +2078,7 @@ export const TourDetailPage = ({
|
||||
</button>
|
||||
|
||||
{/* Delete button overlay (if owner) */}
|
||||
{currentUserId === selectedPhotoForDisplay.uploaderId && !isPublicView && (
|
||||
{currentUserId === selectedPhotoForDisplay.uploaderId && (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
@@ -2090,7 +2092,7 @@ export const TourDetailPage = ({
|
||||
)}
|
||||
|
||||
{/* Bottom metadata details gradient panel overlay */}
|
||||
<div className="absolute bottom-0 inset-x-0 bg-gradient-to-t from-black/95 via-black/50 to-transparent p-6 text-white flex flex-col gap-2 text-left">
|
||||
<div className="absolute bottom-0 inset-x-0 bg-gradient-to-t from-black/60 via-black/20 to-transparent p-6 text-white flex flex-col gap-2 text-left">
|
||||
<div className="flex justify-between items-start gap-4">
|
||||
<div className="flex-1 min-w-0">
|
||||
{selectedPhotoForDisplay.metadata?.title ? (
|
||||
@@ -2110,7 +2112,7 @@ export const TourDetailPage = ({
|
||||
</div>
|
||||
|
||||
{/* Edit Button Overlay */}
|
||||
{!isPublicView && (currentUser?.isAdmin || currentUserId === selectedPhotoForDisplay.uploaderId) && (
|
||||
{((!isPublicView && currentUser?.isAdmin) || (currentUserId && currentUserId === selectedPhotoForDisplay.uploaderId)) && (
|
||||
<button
|
||||
onClick={() => setIsEditingPhoto(true)}
|
||||
className="p-2 bg-white/10 hover:bg-white/20 border border-white/15 rounded-xl text-white hover:text-gray-200 transition-all shrink-0 backdrop-blur-sm"
|
||||
@@ -2137,7 +2139,7 @@ export const TourDetailPage = ({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{selectedPhotoForDisplay.originalUrl && (
|
||||
{(currentUser?.isAdmin || currentUserId === selectedPhotoForDisplay.uploaderId) && selectedPhotoForDisplay.originalUrl && (
|
||||
<a
|
||||
href={selectedPhotoForDisplay.originalUrl}
|
||||
download
|
||||
@@ -2744,6 +2746,25 @@ export const TourDetailPage = ({
|
||||
setEditPhotoLng(lng);
|
||||
}}
|
||||
/>
|
||||
|
||||
{isFullscreen && selectedPhotoForDisplay && (
|
||||
<div
|
||||
className="fixed inset-0 z-[9999] bg-black/95 flex items-center justify-center cursor-zoom-out animate-in fade-in duration-200"
|
||||
onClick={() => setIsFullscreen(false)}
|
||||
>
|
||||
<button
|
||||
onClick={() => setIsFullscreen(false)}
|
||||
className="fixed top-6 right-6 p-3 bg-black/50 hover:bg-black/75 border border-white/10 rounded-full text-white transition-colors z-[10000]"
|
||||
>
|
||||
<X className="w-6 h-6" />
|
||||
</button>
|
||||
<img
|
||||
src={selectedPhotoForDisplay.imageUrl}
|
||||
alt="Fullscreen photo"
|
||||
className="max-w-full max-h-full object-contain select-none animate-in zoom-in-95 duration-200"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user