Sửa lỗi người nhận được liên kết chia sẻ không xem được nội dung Tour

This commit is contained in:
2026-06-16 09:54:32 +07:00
parent 63da413b3c
commit 302a82e887
7 changed files with 217 additions and 183 deletions
+42 -44
View File
@@ -28,6 +28,7 @@ interface TourState {
setActiveLegId: (id: string | null) => void;
setMapCenter: (pos: [number, number]) => void;
fetchTour: (id: string) => Promise<void>;
fetchPublicTourDetails: (tourId: string) => Promise<void>;
fetchPublicTours: () => Promise<void>;
createJoinRequest: (tourId: string, userId?: string) => Promise<any>;
fetchJoinRequests: (tourId: string) => Promise<any[]>;
@@ -47,10 +48,9 @@ export const useTourStore = create<TourState>((set, get) => ({
setActiveLegId: (id) => set({ activeLegId: id }),
setMapCenter: (pos) => set({ mapCenter: pos }),
fetchTour: async (id: string) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const token = localStorage.getItem('token');
try {
const response = await fetch(`${API_BASE}/api/v1/tours/${id}`, {
const response = await fetch(`/api/v1/tours/${id}`, {
headers: { 'Authorization': `Bearer ${token}` }
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
@@ -75,11 +75,10 @@ export const useTourStore = create<TourState>((set, get) => ({
}
},
fetchPublicTours: async () => {
const API_BASE = `http://${window.location.hostname}:3001`;
const token = localStorage.getItem('token');
if (!token) return;
const response = await fetch(`${API_BASE}/api/v1/tours/explore`, {
const response = await fetch(`/api/v1/tours/explore`, {
headers: {
'Authorization': `Bearer ${token}`
}
@@ -89,9 +88,27 @@ export const useTourStore = create<TourState>((set, get) => ({
const data = await response.json();
set({ publicTours: data });
},
fetchPublicTourDetails: async (tourId: string) => {
try {
// Reset state cũ trước khi tải dữ liệu mới
set({ currentTour: null, legs: [], userRole: 'VIEWER_ONLY' });
const response = await fetch(`/api/v1/tours/${tourId}/public`);
if (!response.ok) throw new Error('Không thể tải tour công khai');
const data = await response.json();
const legs = data.legs || [];
set({
currentTour: data,
legs,
userRole: 'VIEWER_ONLY',
activeLegId: legs.length > 0 ? legs[0].id : null
});
} catch (err: any) {
console.error('Lỗi khi tải tour công khai:', err);
}
},
createTour: async (tourData: any) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const response = await fetch(`${API_BASE}/api/v1/tours`, {
const response = await fetch(`/api/v1/tours`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -108,9 +125,8 @@ export const useTourStore = create<TourState>((set, get) => ({
return tour;
},
updateTourDetails: async (tourId: string, data: any) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const token = localStorage.getItem('token');
const response = await fetch(`${API_BASE}/api/v1/tours/${tourId}`, {
const response = await fetch(`/api/v1/tours/${tourId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
@@ -125,8 +141,7 @@ export const useTourStore = create<TourState>((set, get) => ({
}
},
updateTour: async (id: string, data: any) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const response = await fetch(`${API_BASE}/api/v1/tours/${id}`, {
const response = await fetch(`/api/v1/tours/${id}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
@@ -140,8 +155,7 @@ export const useTourStore = create<TourState>((set, get) => ({
get().fetchPublicTours();
},
deleteTour: async (id: string) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const response = await fetch(`${API_BASE}/api/v1/tours/${id}`, {
const response = await fetch(`/api/v1/tours/${id}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
@@ -157,8 +171,7 @@ export const useTourStore = create<TourState>((set, get) => ({
get().fetchPublicTours();
},
addLeg: async (tourId: string, data: any) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const response = await fetch(`${API_BASE}/api/v1/tours/${tourId}/legs`, {
const response = await fetch(`/api/v1/tours/${tourId}/legs`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -170,8 +183,7 @@ export const useTourStore = create<TourState>((set, get) => ({
get().fetchTour(tourId);
},
initializeLegs: async (tourId: string, count: number) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const response = await fetch(`${API_BASE}/api/v1/tours/${tourId}/legs/batch`, {
const response = await fetch(`/api/v1/tours/${tourId}/legs/batch`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -183,8 +195,7 @@ export const useTourStore = create<TourState>((set, get) => ({
await get().fetchTour(tourId);
},
updateLeg: async (legId: string, data: any) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const response = await fetch(`${API_BASE}/api/v1/legs/${legId}`, {
const response = await fetch(`/api/v1/legs/${legId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
@@ -198,8 +209,7 @@ export const useTourStore = create<TourState>((set, get) => ({
if (currentTour) get().fetchTour(currentTour.id);
},
deleteLeg: async (legId: string) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const response = await fetch(`${API_BASE}/api/v1/legs/${legId}`, {
const response = await fetch(`/api/v1/legs/${legId}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
@@ -214,8 +224,7 @@ export const useTourStore = create<TourState>((set, get) => ({
if (currentTour) get().fetchTour(currentTour.id);
},
addLocation: async (tourId: string, locationData: any) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const response = await fetch(`${API_BASE}/api/v1/tours/${tourId}/locations`, {
const response = await fetch(`/api/v1/tours/${tourId}/locations`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -228,8 +237,7 @@ export const useTourStore = create<TourState>((set, get) => ({
get().fetchTour(tourId);
},
updateLocation: async (locationId: string, data: any) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const response = await fetch(`${API_BASE}/api/v1/locations/${locationId}`, {
const response = await fetch(`/api/v1/locations/${locationId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
@@ -243,8 +251,7 @@ export const useTourStore = create<TourState>((set, get) => ({
if (currentTour) get().fetchTour(currentTour.id);
},
deleteLocation: async (locationId: string) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const response = await fetch(`${API_BASE}/api/v1/locations/${locationId}`, {
const response = await fetch(`/api/v1/locations/${locationId}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
@@ -256,8 +263,7 @@ export const useTourStore = create<TourState>((set, get) => ({
if (currentTour) get().fetchTour(currentTour.id);
},
updateTourStartPoint: async (tourId: string, data: any) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const response = await fetch(`${API_BASE}/api/v1/tours/${tourId}/start-point`, {
const response = await fetch(`/api/v1/tours/${tourId}/start-point`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -271,8 +277,7 @@ export const useTourStore = create<TourState>((set, get) => ({
await get().fetchTour(tourId);
},
updateTourEndPoint: async (tourId: string, data: any) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const response = await fetch(`${API_BASE}/api/v1/tours/${tourId}/end-point`, {
const response = await fetch(`/api/v1/tours/${tourId}/end-point`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -284,8 +289,7 @@ export const useTourStore = create<TourState>((set, get) => ({
await get().fetchTour(tourId);
},
optimizeRouting: async (legId: string) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const response = await fetch(`${API_BASE}/api/v1/routing/optimize/${legId}`, {
const response = await fetch(`/api/v1/routing/optimize/${legId}`, {
method: 'POST'
});
const { locations, totalDistance } = await response.json();
@@ -299,8 +303,7 @@ export const useTourStore = create<TourState>((set, get) => ({
}
},
removeMember: async (tourId: string, userId: string) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const response = await fetch(`${API_BASE}/api/v1/tours/${tourId}/members/${userId}`, {
const response = await fetch(`/api/v1/tours/${tourId}/members/${userId}`, {
method: 'DELETE',
headers: {
Authorization: `Bearer ${localStorage.getItem('token')}`,
@@ -311,8 +314,7 @@ export const useTourStore = create<TourState>((set, get) => ({
if (currentTour) get().fetchTour(currentTour.id);
},
addMember: async (tourId: string, member: { userId: string; role?: string }) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const response = await fetch(`${API_BASE}/api/v1/tours/${tourId}/members`, {
const response = await fetch(`/api/v1/tours/${tourId}/members`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -328,8 +330,7 @@ export const useTourStore = create<TourState>((set, get) => ({
if (currentTour) get().fetchTour(currentTour.id);
},
createJoinRequest: async (tourId: string, userId?: string) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const response = await fetch(`${API_BASE}/api/v1/tours/${tourId}/join-requests`, {
const response = await fetch(`/api/v1/tours/${tourId}/join-requests`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -344,8 +345,7 @@ export const useTourStore = create<TourState>((set, get) => ({
return response.json();
},
fetchJoinRequests: async (tourId: string) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const response = await fetch(`${API_BASE}/api/v1/tours/${tourId}/join-requests`, {
const response = await fetch(`/api/v1/tours/${tourId}/join-requests`, {
headers: {
Authorization: `Bearer ${localStorage.getItem('token')}`
}
@@ -357,8 +357,7 @@ export const useTourStore = create<TourState>((set, get) => ({
return response.json();
},
acceptJoinRequest: async (tourId: string, requestId: string) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const response = await fetch(`${API_BASE}/api/v1/tours/${tourId}/join-requests/${requestId}/accept`, {
const response = await fetch(`/api/v1/tours/${tourId}/join-requests/${requestId}/accept`, {
method: 'POST',
headers: {
Authorization: `Bearer ${localStorage.getItem('token')}`
@@ -372,8 +371,7 @@ export const useTourStore = create<TourState>((set, get) => ({
if (currentTour) get().fetchTour(currentTour.id);
},
rejectJoinRequest: async (tourId: string, requestId: string) => {
const API_BASE = `http://${window.location.hostname}:3001`;
const response = await fetch(`${API_BASE}/api/v1/tours/${tourId}/join-requests/${requestId}/reject`, {
const response = await fetch(`/api/v1/tours/${tourId}/join-requests/${requestId}/reject`, {
method: 'POST',
headers: {
Authorization: `Bearer ${localStorage.getItem('token')}`