fix: cho phép người đã tải ảnh lên được quyền chỉnh sửa

This commit is contained in:
2026-06-20 08:27:58 +07:00
parent ac11bb56db
commit ae74035ad5
12 changed files with 179 additions and 83 deletions
+29 -8
View File
@@ -1,4 +1,4 @@
import React, { useEffect, useState, useMemo } from 'react';
import { useEffect, useState, useMemo } from 'react';
import { ChevronLeft, Image as ImageIcon, Download, Calendar, MapPin, Loader2, Filter, X, Trash2, Edit, Heart } from 'lucide-react';
import { useNotification } from '@/hooks/useNotification';
import { useConfirm } from '@/hooks/useConfirm';
@@ -22,6 +22,7 @@ export const MyPhotosPage = ({ onBack }: { onBack: () => void }) => {
const [isSavingEdit, setIsSavingEdit] = useState(false);
const [isMapOpen, setIsMapOpen] = useState(false);
const [resolvedAddress, setResolvedAddress] = useState<string>('');
const [isFullscreen, setIsFullscreen] = useState(false);
useEffect(() => {
const lat = selectedPhotoForDisplay?.metadata?.lat;
@@ -75,7 +76,7 @@ export const MyPhotosPage = ({ onBack }: { onBack: () => void }) => {
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: editTitle,
@@ -103,7 +104,7 @@ export const MyPhotosPage = ({ onBack }: { onBack: () => void }) => {
};
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);
@@ -120,7 +121,7 @@ export const MyPhotosPage = ({ onBack }: { onBack: () => void }) => {
const handleToggleLike = async () => {
if (!selectedPhotoForDisplay) return;
const token = localStorage.getItem('token');
const token = localStorage.getItem('token') || localStorage.getItem('guest_token');
if (!token) return;
try {
@@ -146,7 +147,7 @@ export const MyPhotosPage = ({ onBack }: { onBack: () => void }) => {
try {
const response = await fetch('/api/v1/users/me/photos', {
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
'Authorization': `Bearer ${localStorage.getItem('token') || localStorage.getItem('guest_token')}`
}
});
if (!response.ok) throw new Error('Failed to fetch photos');
@@ -217,7 +218,7 @@ export const MyPhotosPage = ({ onBack }: { onBack: () => void }) => {
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')}`
}
});
@@ -347,7 +348,8 @@ export const MyPhotosPage = ({ onBack }: { onBack: () => void }) => {
<img
src={selectedPhotoForDisplay.imageUrl || selectedPhotoForDisplay.originalUrl}
alt="Selected 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) */}
@@ -378,7 +380,7 @@ export const MyPhotosPage = ({ onBack }: { onBack: () => void }) => {
</button>
{/* 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">
<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 ? (
@@ -584,6 +586,25 @@ export const MyPhotosPage = ({ onBack }: { onBack: () => void }) => {
setEditLng(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 || selectedPhotoForDisplay.originalUrl}
alt="Fullscreen photo"
className="max-w-full max-h-full object-contain select-none animate-in zoom-in-95 duration-200"
/>
</div>
)}
</div>
);
};