Thêm tính năng owner có thể thêm thành viên, member thêm thành viên sẽ pending

This commit is contained in:
2026-06-14 22:14:40 +07:00
parent 7cc724a133
commit c6341aa12f
16 changed files with 395 additions and 23 deletions
+8 -6
View File
@@ -6,6 +6,7 @@ import { useTourStore } from './useTourStore.js';
import { AddLocationModal } from './AddLocationModal.js';
import { AddMemberModal } from './AddMemberModal.js';
import { ConfirmModal } from './ConfirmModal.js';
import { NotificationModal, useNotificationModal } from './components/NotificationModal.js';
import { MapContainer, TileLayer, Marker, Popup, useMapEvents, Polyline } from 'react-leaflet';
import _MarkerClusterGroup from 'react-leaflet-cluster';
const MarkerClusterGroup = _MarkerClusterGroup.default || _MarkerClusterGroup;
@@ -104,6 +105,7 @@ export const TourDetailPage = ({ onBack }) => {
const [joinRequestActionId, setJoinRequestActionId] = useState(null);
const [confirmState, setConfirmState] = useState({ open: false });
const { currentTour, legs, fetchTour, fetchPublicTours, publicTours, userRole, mapCenter, setMapCenter, updateTourStartPoint, updateTourEndPoint, initializeLegs, addLocation, addMember, removeMember, fetchJoinRequests, acceptJoinRequest, rejectJoinRequest } = useTourStore();
const notificationModal = useNotificationModal();
const [initialViewState] = useState(() => {
const saved = localStorage.getItem('map_view_state');
if (saved) {
@@ -267,7 +269,7 @@ export const TourDetailPage = ({ onBack }) => {
setJoinRequests((prev) => prev.filter((r) => r.id !== req.id));
}
catch (e) {
alert(e.message || 'Không thể chấp nhận yêu cầu');
notificationModal.openModal('Thông báo', e.message || 'Không thể chấp nhận yêu cầu', 'error');
}
finally {
setJoinRequestActionId(null);
@@ -290,7 +292,7 @@ export const TourDetailPage = ({ onBack }) => {
setJoinRequests((prev) => prev.filter((r) => r.id !== req.id));
}
catch (e) {
alert(e.message || 'Không thể từ chối yêu cầu');
notificationModal.openModal('Thông báo', e.message || 'Không thể từ chối yêu cầu', 'error');
}
finally {
setJoinRequestActionId(null);
@@ -333,7 +335,7 @@ export const TourDetailPage = ({ onBack }) => {
setJoinRequests((prev) => prev.filter((r) => r.id !== req.id));
}
catch (e) {
alert(e.message || 'Không thể chấp nhận yêu cầu');
notificationModal.openModal('Thông báo', e.message || 'Không thể chấp nhận yêu cầu', 'error');
}
finally {
setJoinRequestActionId(null);
@@ -355,7 +357,7 @@ export const TourDetailPage = ({ onBack }) => {
setJoinRequests((prev) => prev.filter((r) => r.id !== req.id));
}
catch (e) {
alert(e.message || 'Không thể từ chối yêu cầu');
notificationModal.openModal('Thông báo', e.message || 'Không thể từ chối yêu cầu', 'error');
}
finally {
setJoinRequestActionId(null);
@@ -376,11 +378,11 @@ export const TourDetailPage = ({ onBack }) => {
setIsMemberDetailOpen(false);
}
catch (e) {
alert('Không thể xóa thành viên');
notificationModal.openModal('Thông báo', 'Không thể xóa thành viên', 'error');
}
}, className: "px-3 py-2 bg-red-600 hover:bg-red-700 text-white rounded-xl text-sm font-bold", children: "X\u00F3a" })), canEdit && selectedMember.role === 'OWNER' && (_jsx("button", { onClick: () => {
setIsMemberDetailOpen(false);
setIsAddMemberOpen(true);
}, className: "px-3 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-xl text-sm font-bold", children: "M\u1EDDi th\u00EAm ng\u01B0\u1EDDi" }))] })] })] })), _jsx(ConfirmModal, { isOpen: confirmState.open, title: confirmState.title, message: confirmState.message, onConfirm: () => confirmState.onConfirm?.(), onCancel: () => setConfirmState({ open: false }) })] }));
}, className: "px-3 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-xl text-sm font-bold", children: "M\u1EDDi th\u00EAm ng\u01B0\u1EDDi" }))] })] })] })), _jsx(ConfirmModal, { isOpen: confirmState.open, title: confirmState.title, message: confirmState.message, onConfirm: () => confirmState.onConfirm?.(), onCancel: () => setConfirmState({ open: false }) }), _jsx(NotificationModal, { isOpen: notificationModal.modalState?.isOpen ?? false, title: notificationModal.modalState?.title, message: notificationModal.modalState?.message, type: notificationModal.modalState?.type, onConfirm: () => notificationModal.closeModal() })] }));
};
//# sourceMappingURL=TourDetailPage.js.map