geo distance meter

This commit is contained in:
2025-11-06 15:34:51 +09:00
parent 0bbeb0767b
commit 240864617f
8 changed files with 290 additions and 11 deletions

View File

@@ -137,6 +137,11 @@ export class CallbackHandlers {
console.log(`User ${telegramId} confirmed city edit: ${editState.tempCity}`);
// Обновляем город в профиле
await this.messageHandlers.updateProfileField(telegramId, 'city', editState.tempCity);
// Обновляем координаты, если они есть
if (editState.tempLocation) {
console.log(`User ${telegramId} updating location: lat=${editState.tempLocation.latitude}, lon=${editState.tempLocation.longitude}`);
await this.messageHandlers.updateProfileField(telegramId, 'location', editState.tempLocation);
}
// Очищаем состояние
this.messageHandlers.clearProfileEditState(telegramId);
// Убираем inline-кнопки
@@ -1061,7 +1066,20 @@ export class CallbackHandlers {
const mainPhotoFileId = profile.photos[0]; // Первое фото - главное
let profileText = '👤 ' + profile.name + ', ' + profile.age + '\n';
profileText += '📍 ' + (profile.city || 'Не указан') + '\n';
profileText += '📍 ' + (profile.city || 'Не указан');
// Добавляем расстояние, если это не владелец профиля и есть viewerId
if (!isOwner && viewerId) {
const viewerProfile = await this.profileService.getProfileByTelegramId(viewerId);
if (viewerProfile && viewerProfile.location && profile.location) {
const distance = viewerProfile.getDistanceTo(profile);
if (distance !== null) {
profileText += ` (${Math.round(distance)} км)`;
}
}
}
profileText += '\n';
if (profile.job) profileText += '💼 ' + profile.job + '\n';
if (profile.education) profileText += '🎓 ' + profile.education + '\n';
if (profile.height) profileText += '📏 ' + profile.height + ' см\n';
@@ -1204,8 +1222,21 @@ export class CallbackHandlers {
const candidatePhotoFileId = candidate.photos[0]; // Первое фото - главное
// Получаем профиль текущего пользователя для вычисления расстояния
const userProfile = await this.profileService.getProfileByTelegramId(telegramId);
let candidateText = candidate.name + ', ' + candidate.age + '\n';
candidateText += '📍 ' + (candidate.city || 'Не указан') + '\n';
candidateText += '📍 ' + (candidate.city || 'Не указан');
// Добавляем расстояние, если есть координаты у обоих пользователей
if (userProfile && userProfile.location && candidate.location) {
const distance = userProfile.getDistanceTo(candidate);
if (distance !== null) {
candidateText += ` (${Math.round(distance)} км)`;
}
}
candidateText += '\n';
if (candidate.job) candidateText += '💼 ' + candidate.job + '\n';
if (candidate.education) candidateText += '🎓 ' + candidate.education + '\n';
if (candidate.height) candidateText += '📏 ' + candidate.height + ' см\n';

View File

@@ -21,6 +21,7 @@ interface ProfileEditState {
waitingForInput: boolean;
field: string;
tempCity?: string; // Временное хранение города для подтверждения
tempLocation?: { latitude: number; longitude: number }; // Временное хранение координат
}
export class MessageHandlers {
@@ -268,6 +269,7 @@ export class MessageHandlers {
interestedIn: interestedIn,
bio: profileData.bio,
city: profileData.city,
location: profileData.location, // Добавляем координаты
photos: profileData.photos,
interests: [],
searchPreferences: {
@@ -598,6 +600,10 @@ export class MessageHandlers {
// В БД поле называется 'city' (не 'location')
updates.city = value;
break;
case 'location':
// Обновляем координаты
updates.location = value;
break;
case 'job':
// В БД поле называется 'occupation', но мы используем job в модели
updates.job = value;
@@ -705,8 +711,12 @@ export class MessageHandlers {
// Логируем результат
console.log(`KakaoMaps resolved for user ${userId}: city=${cityName}, address=${displayAddress}`);
// Временно сохраняем город (пока не подтвержден пользователем)
// Временно сохраняем город И координаты (пока не подтверждены пользователем)
userState.data.city = cityName;
userState.data.location = {
latitude: msg.location.latitude,
longitude: msg.location.longitude
};
userState.step = 'confirm_city';
// Отправляем пользователю информацию с кнопками подтверждения
@@ -794,10 +804,14 @@ export class MessageHandlers {
// Логируем результат
console.log(`KakaoMaps resolved for user ${userId} during edit: city=${cityName}, address=${displayAddress}`);
// Временно сохраняем город в состояние редактирования
// Временно сохраняем город И координаты в состояние редактирования
const editState = this.profileEditStates.get(userId);
if (editState) {
editState.tempCity = cityName;
editState.tempLocation = {
latitude: msg.location.latitude,
longitude: msg.location.longitude
};
}
// Отправляем пользователю информацию с кнопками подтверждения

View File

@@ -50,9 +50,9 @@ export class ProfileService {
await query(`
INSERT INTO profiles (
id, user_id, name, age, gender, interested_in, bio, photos,
city, education, job, height, religion, dating_goal,
city, education, job, height, location_lat, location_lon, religion, dating_goal,
is_verified, is_visible, created_at, updated_at
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18)
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20)
ON CONFLICT (user_id) DO UPDATE SET
name = EXCLUDED.name,
age = EXCLUDED.age,
@@ -64,6 +64,8 @@ export class ProfileService {
education = EXCLUDED.education,
job = EXCLUDED.job,
height = EXCLUDED.height,
location_lat = EXCLUDED.location_lat,
location_lon = EXCLUDED.location_lon,
religion = EXCLUDED.religion,
dating_goal = EXCLUDED.dating_goal,
is_verified = EXCLUDED.is_verified,
@@ -72,7 +74,10 @@ export class ProfileService {
`, [
profileId, userId, profile.name, profile.age, profile.gender, profile.interestedIn,
profile.bio, profile.photos, profile.city, profile.education, profile.job,
profile.height, profile.religion, profile.datingGoal,
profile.height,
profile.location?.latitude || null,
profile.location?.longitude || null,
profile.religion, profile.datingGoal,
profile.isVerified, profile.isVisible, profile.createdAt, profile.updatedAt
]);
@@ -190,8 +195,14 @@ export class ProfileService {
updateValues.push(Array.isArray(value) ? value : [value]);
break;
case 'location':
// Пропускаем обработку местоположения, так как колонки location нет
console.log('Skipping location update - column does not exist');
// Сохраняем координаты в location_lat и location_lon
if (value && typeof value === 'object' && 'latitude' in value && 'longitude' in value) {
updateFields.push(`location_lat = $${paramIndex++}`);
updateValues.push(value.latitude);
updateFields.push(`location_lon = $${paramIndex++}`);
updateValues.push(value.longitude);
console.log(`Updating location: lat=${value.latitude}, lon=${value.longitude}`);
}
break;
case 'searchPreferences':
// Поля search preferences больше не хранятся в БД, пропускаем
@@ -475,7 +486,10 @@ export class ProfileService {
drinking: undefined,
kids: undefined
}, // Пропускаем lifestyle, так как этих колонок нет
location: undefined, // Пропускаем location, так как этих колонок нет
location: (entity.location_lat && entity.location_lon) ? {
latitude: parseFloat(entity.location_lat),
longitude: parseFloat(entity.location_lon)
} : undefined,
searchPreferences: {
minAge: 18,
maxAge: 50,