fix: guest hiển thị lời mời này không tồn tại
|
After Width: | Height: | Size: 264 KiB |
|
After Width: | Height: | Size: 562 KiB |
|
Before Width: | Height: | Size: 224 KiB |
|
Before Width: | Height: | Size: 199 KiB |
|
After Width: | Height: | Size: 228 KiB |
|
After Width: | Height: | Size: 250 KiB |
|
After Width: | Height: | Size: 239 KiB |
|
After Width: | Height: | Size: 365 KiB |
|
After Width: | Height: | Size: 225 KiB |
|
After Width: | Height: | Size: 190 KiB |
|
After Width: | Height: | Size: 270 KiB |
|
After Width: | Height: | Size: 233 KiB |
|
After Width: | Height: | Size: 646 KiB |
|
Before Width: | Height: | Size: 224 KiB |
|
Before Width: | Height: | Size: 199 KiB |
|
After Width: | Height: | Size: 645 KiB |
|
After Width: | Height: | Size: 263 KiB |
|
After Width: | Height: | Size: 561 KiB |
|
After Width: | Height: | Size: 228 KiB |
|
After Width: | Height: | Size: 250 KiB |
|
After Width: | Height: | Size: 238 KiB |
|
After Width: | Height: | Size: 364 KiB |
|
After Width: | Height: | Size: 225 KiB |
|
After Width: | Height: | Size: 190 KiB |
|
After Width: | Height: | Size: 270 KiB |
|
After Width: | Height: | Size: 233 KiB |
@@ -0,0 +1,73 @@
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
container_name: yotrip-db
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: password
|
||||
POSTGRES_DB: travel_db
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- pg_data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U postgres -d travel_db"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: yotrip-redis
|
||||
ports:
|
||||
- "6379:6379"
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: ./backend
|
||||
target: development
|
||||
container_name: yotrip-backend
|
||||
command: >
|
||||
sh -c "npx prisma migrate dev --schema=prisma/schema.prisma && npm run start:dev"
|
||||
ports:
|
||||
- "3001:3001"
|
||||
volumes:
|
||||
- ./backend:/usr/src/app
|
||||
- /usr/src/app/node_modules
|
||||
environment:
|
||||
DATABASE_URL: "postgresql://postgres:password@postgres:5432/travel_db?schema=public"
|
||||
REDIS_URL: "redis://redis:6379"
|
||||
PORT: 3001
|
||||
ADMIN_SECRET_KEY: "yotrip_secret_admin_key"
|
||||
JWT_SECRET: "super-secret"
|
||||
FRONTEND_URL: "http://localhost:5173"
|
||||
NODE_ENV: development
|
||||
SMTP_HOST: "${SMTP_HOST}"
|
||||
SMTP_PORT: "${SMTP_PORT}"
|
||||
SMTP_SECURE: "${SMTP_SECURE}"
|
||||
SMTP_USER: "${SMTP_USER}"
|
||||
SMTP_PASS: "${SMTP_PASS}"
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_started
|
||||
|
||||
frontend:
|
||||
build:
|
||||
context: ./frontend
|
||||
target: development
|
||||
container_name: yotrip-frontend
|
||||
command: npm run dev -- --host 0.0.0.0
|
||||
ports:
|
||||
- "5173:5173"
|
||||
volumes:
|
||||
- ./frontend:/usr/src/app
|
||||
- /usr/src/app/node_modules
|
||||
environment:
|
||||
VITE_API_URL: "http://localhost:3001"
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
volumes:
|
||||
pg_data:
|
||||
@@ -1,17 +1,14 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
container_name: yotrip-db
|
||||
container_name: yotrip-db-prod
|
||||
restart: always
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: password
|
||||
POSTGRES_DB: travel_db
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- pg_data:/var/lib/postgresql/data
|
||||
- pg_data_prod:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U postgres -d travel_db"]
|
||||
interval: 5s
|
||||
@@ -20,30 +17,29 @@ services:
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: yotrip-redis
|
||||
ports:
|
||||
- "6379:6379"
|
||||
container_name: yotrip-redis-prod
|
||||
restart: always
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: ./backend
|
||||
target: development
|
||||
container_name: yotrip-backend
|
||||
target: production
|
||||
container_name: yotrip-backend-prod
|
||||
restart: always
|
||||
command: >
|
||||
sh -c "npx prisma migrate dev --schema=prisma/schema.prisma && npm run start:dev"
|
||||
sh -c "npx prisma migrate deploy --schema=prisma/schema.prisma && node dist/src/main.js"
|
||||
ports:
|
||||
- "3001:3001"
|
||||
volumes:
|
||||
- ./backend:/usr/src/app
|
||||
- /usr/src/app/node_modules
|
||||
- ./backend/uploads:/usr/src/app/uploads
|
||||
environment:
|
||||
DATABASE_URL: "postgresql://postgres:password@postgres:5432/travel_db?schema=public"
|
||||
REDIS_URL: "redis://redis:6379"
|
||||
PORT: 3001
|
||||
ADMIN_SECRET_KEY: "yotrip_secret_admin_key"
|
||||
ADMIN_SECRET_KEY: "${ADMIN_SECRET_KEY}"
|
||||
JWT_SECRET: "super-secret"
|
||||
FRONTEND_URL: "http://localhost:5173"
|
||||
NODE_ENV: development
|
||||
FRONTEND_URL: "${FRONTEND_URL}"
|
||||
NODE_ENV: production
|
||||
SMTP_HOST: "${SMTP_HOST}"
|
||||
SMTP_PORT: "${SMTP_PORT}"
|
||||
SMTP_SECURE: "${SMTP_SECURE}"
|
||||
@@ -58,18 +54,15 @@ services:
|
||||
frontend:
|
||||
build:
|
||||
context: ./frontend
|
||||
target: development
|
||||
container_name: yotrip-frontend
|
||||
command: npm run dev -- --host 0.0.0.0
|
||||
target: production
|
||||
args:
|
||||
- VITE_GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID}
|
||||
container_name: yotrip-frontend-prod
|
||||
restart: always
|
||||
ports:
|
||||
- "5173:5173"
|
||||
volumes:
|
||||
- ./frontend:/usr/src/app
|
||||
- /usr/src/app/node_modules
|
||||
environment:
|
||||
VITE_API_URL: "http://localhost:3001"
|
||||
- "3002:80"
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
volumes:
|
||||
pg_data:
|
||||
pg_data_prod:
|
||||
|
||||
@@ -175,19 +175,23 @@ export const LandingPage: React.FC<LandingPageProps> = ({ onGoToSignup, onGoToMa
|
||||
new Promise<null>((resolve) => setTimeout(() => resolve(null), 4500))
|
||||
]);
|
||||
|
||||
// 1. Tạo tài khoản khách và lấy token
|
||||
let guestToken = localStorage.getItem('guest_token');
|
||||
let guestUser = JSON.parse(localStorage.getItem('guest_user') || 'null');
|
||||
|
||||
if (!guestToken) {
|
||||
const guestRes = await fetch('/api/v1/auth/create-guest', { method: 'POST' });
|
||||
if (!guestRes.ok) throw new Error('Không thể tạo phiên khách.');
|
||||
const guestData = await guestRes.json();
|
||||
guestToken = guestData.access_token;
|
||||
guestUser = guestData.user;
|
||||
localStorage.setItem('guest_token', guestToken!);
|
||||
localStorage.setItem('guest_user', JSON.stringify(guestUser));
|
||||
}
|
||||
// 1. Xóa token cũ nếu có để đảm bảo guest không bị nhầm lẫn
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('user');
|
||||
|
||||
// 2. Tạo tài khoản khách và lấy token
|
||||
let guestToken = localStorage.getItem('guest_token');
|
||||
let guestUser = JSON.parse(localStorage.getItem('guest_user') || 'null');
|
||||
|
||||
if (!guestToken) {
|
||||
const guestRes = await fetch('/api/v1/auth/create-guest', { method: 'POST' });
|
||||
if (!guestRes.ok) throw new Error('Không thể tạo phiên khách.');
|
||||
const guestData = await guestRes.json();
|
||||
guestToken = guestData.access_token;
|
||||
guestUser = guestData.user;
|
||||
localStorage.setItem('guest_token', guestToken!);
|
||||
localStorage.setItem('guest_user', JSON.stringify(guestUser));
|
||||
}
|
||||
|
||||
// 2. Tải ảnh lên
|
||||
const formData = new FormData();
|
||||
@@ -230,18 +234,17 @@ export const LandingPage: React.FC<LandingPageProps> = ({ onGoToSignup, onGoToMa
|
||||
throw new Error(errorData.message || 'Tải ảnh thất bại.');
|
||||
}
|
||||
|
||||
notify({ title: 'Thành công!', message: 'Ảnh của bạn đã được tải lên.', type: 'success' });
|
||||
|
||||
// Cập nhật lại danh sách ảnh lập tức
|
||||
await fetchPublicPhotos();
|
||||
setCurrentBgIndex(0);
|
||||
notify({ title: 'Thành công!', message: 'Ảnh của bạn đã được tải lên.', type: 'success' });
|
||||
|
||||
// Đăng nhập luôn bằng tài khoản khách này để người dùng xem được ảnh của mình trên bản đồ
|
||||
localStorage.setItem('token', guestToken!);
|
||||
localStorage.setItem('user', JSON.stringify(guestUser));
|
||||
if (onLoginSuccess) {
|
||||
onLoginSuccess(guestUser);
|
||||
}
|
||||
// Xóa pendingInviteToken và parameter token khỏi URL để tránh tự động chuyển sang JoinTourPage
|
||||
localStorage.removeItem('pendingInviteToken');
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.delete('token');
|
||||
window.history.replaceState({}, '', url.toString());
|
||||
|
||||
// Cập nhật lại danh sách ảnh lập tức
|
||||
await fetchPublicPhotos();
|
||||
setCurrentBgIndex(0);
|
||||
|
||||
} catch (error: any) {
|
||||
notify({ title: 'Lỗi', message: error.message, type: 'error' });
|
||||
|
||||