mirror of
https://github.com/orangecoding/fredy.git
synced 2026-06-16 12:31:07 +00:00
Calculating the distance (#255)
* migra for distance * adding distance calculator * adding ability to store home address * improve distance calculation * calculating distance * show distance in grid view * upgrading dependencies * moving to react 19 * ability to clone a job * fixing tests * polishing
This commit is contained in:
committed by
GitHub
parent
51b4e51f3f
commit
4dd0370ec1
@@ -502,3 +502,57 @@ export const getGeocoordinatesByAddress = (address) => {
|
||||
)[0];
|
||||
return row ? { lat: row.latitude, lng: row.longitude } : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return all active listings for a given job that have geocoordinates but no distance set.
|
||||
*
|
||||
* @param {string} jobId
|
||||
* @returns {Object[]}
|
||||
*/
|
||||
export const getListingsToCalculateDistance = (jobId) => {
|
||||
return SqliteConnection.query(
|
||||
`SELECT id, latitude, longitude
|
||||
FROM listings
|
||||
WHERE job_id = @jobId
|
||||
AND is_active = 1
|
||||
AND latitude IS NOT NULL
|
||||
AND longitude IS NOT NULL
|
||||
AND distance_to_destination IS NULL`,
|
||||
{ jobId },
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return all active listings for a given user (across all jobs) that have geocoordinates.
|
||||
*
|
||||
* @param {string} userId
|
||||
* @returns {Object[]}
|
||||
*/
|
||||
export const getListingsForUserToCalculateDistance = (userId) => {
|
||||
return SqliteConnection.query(
|
||||
`SELECT l.id, l.latitude, l.longitude
|
||||
FROM listings l
|
||||
JOIN jobs j ON l.job_id = j.id
|
||||
WHERE j.user_id = @userId
|
||||
AND l.is_active = 1
|
||||
AND l.latitude IS NOT NULL
|
||||
AND l.longitude IS NOT NULL`,
|
||||
{ userId },
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the distance to destination for a listing.
|
||||
*
|
||||
* @param {string} id
|
||||
* @param {number} distance
|
||||
* @returns {void}
|
||||
*/
|
||||
export const updateListingDistance = (id, distance) => {
|
||||
SqliteConnection.execute(
|
||||
`UPDATE listings
|
||||
SET distance_to_destination = @distance
|
||||
WHERE id = @id`,
|
||||
{ id, distance },
|
||||
);
|
||||
};
|
||||
|
||||
12
lib/services/storage/migrations/sql/8.distances.js
Normal file
12
lib/services/storage/migrations/sql/8.distances.js
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) 2026 by Christian Kellner.
|
||||
* Licensed under Apache-2.0 with Commons Clause and Attribution/Naming Clause
|
||||
*/
|
||||
|
||||
// Migration: Removing city field and adding distance field
|
||||
|
||||
export function up(db) {
|
||||
db.exec(`
|
||||
ALTER TABLE listings ADD COLUMN distance_to_destination INTEGER;
|
||||
`);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2026 by Christian Kellner.
|
||||
* Licensed under Apache-2.0 with Commons Clause and Attribution/Naming Clause
|
||||
*/
|
||||
|
||||
export function up(db) {
|
||||
// 1. Remove old unique index
|
||||
db.exec(`DROP INDEX IF EXISTS idx_settings_name;`);
|
||||
|
||||
// 2. Add new unique index for name and user_id.
|
||||
// Since user_id can be NULL, we need a special index or use coalesce for the index.
|
||||
// In SQLite, multiple NULLs are allowed in a UNIQUE index, which is fine for our global settings (user_id IS NULL).
|
||||
// But we want only one global setting for a given name.
|
||||
// Actually, in SQLite, UNIQUE allows multiple NULL values.
|
||||
// To have only one NULL user_id for a name, we can use a partial index or COALESCE.
|
||||
|
||||
db.exec(`
|
||||
CREATE UNIQUE INDEX idx_settings_name_user_id ON settings (name, IFNULL(user_id, 'GLOBAL_SETTING'));
|
||||
`);
|
||||
}
|
||||
@@ -37,12 +37,25 @@ function compileSettings(rows, configValues) {
|
||||
* @returns {Record<string, any>}
|
||||
*/
|
||||
export async function refreshSettingsCache() {
|
||||
const rows = SqliteConnection.query(`SELECT name, value FROM settings`);
|
||||
const rows = SqliteConnection.query(`SELECT name, value FROM settings WHERE user_id IS NULL`);
|
||||
const configValues = await readConfigFromStorage();
|
||||
cachedSettingsConfig = compileSettings(rows, configValues);
|
||||
return cachedSettingsConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves user-specific settings from the database.
|
||||
* @param {string} userId
|
||||
* @returns {Record<string, any>}
|
||||
*/
|
||||
export function getUserSettings(userId) {
|
||||
if (!userId || typeof userId !== 'string') {
|
||||
return {};
|
||||
}
|
||||
const userRows = SqliteConnection.query(`SELECT name, value FROM settings WHERE user_id = @userId`, { userId });
|
||||
return compileSettings(userRows, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the compiled settings config. Loads it once and caches the result.
|
||||
* @returns {Record<string, any>}
|
||||
@@ -83,10 +96,12 @@ export function upsertSettings(settingsMapOrEntry, userId = null) {
|
||||
SqliteConnection.execute(
|
||||
`INSERT INTO settings (id, create_date, name, value, user_id)
|
||||
VALUES (@id, @create_date, @name, @value, @userId)
|
||||
ON CONFLICT(name) DO UPDATE SET value = excluded.value`,
|
||||
ON CONFLICT(name, IFNULL(user_id, 'GLOBAL_SETTING')) DO UPDATE SET value = excluded.value`,
|
||||
{ id, create_date, name, value: json, userId },
|
||||
);
|
||||
}
|
||||
// keep cache in sync
|
||||
refreshSettingsCache();
|
||||
// keep cache in sync (only for global settings)
|
||||
if (userId == null) {
|
||||
refreshSettingsCache();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user