feat: trim for aplhabet sort

This commit is contained in:
2026-04-06 13:23:25 +03:00
parent a58f438dce
commit 4b02c6e9d3
25 changed files with 73 additions and 59 deletions

View File

@@ -74,7 +74,7 @@ export const ArticleListPage = observer(() => {
];
const rows = useMemo(() => {
const query = searchQuery.toLowerCase();
const query = searchQuery.trim().toLowerCase();
return articleList[language].data
.filter((article) => !query || (article.heading ?? "").toLowerCase().includes(query))
.map((article) => ({

View File

@@ -121,7 +121,7 @@ export const CarrierListPage = observer(() => {
const canWriteCarriers = authStore.canWrite("carriers");
const rows = useMemo(() => {
const query = searchQuery.toLowerCase();
const query = searchQuery.trim().toLowerCase();
return (carriers[language].data ?? [])
.filter((carrier) => !allowedCityIds || allowedCityIds.includes(carrier.city_id))
.filter(

View File

@@ -59,7 +59,7 @@ export const CityListPage = observer(() => {
}, [cities, countryStore.countries, language, isLoading]);
const filteredRows = useMemo(() => {
const query = searchQuery.toLowerCase();
const query = searchQuery.trim().toLowerCase();
if (!query) return rows;
return rows.filter((row) => {
const cityName = (row.name ?? "").toLowerCase();

View File

@@ -74,7 +74,7 @@ export const CountryListPage = observer(() => {
];
const rows = useMemo(() => {
const query = searchQuery.toLowerCase();
const query = searchQuery.trim().toLowerCase();
return (countries[language]?.data ?? [])
.filter((country) => !query || (country.name ?? "").toLowerCase().includes(query))
.map((country) => ({

View File

@@ -244,9 +244,9 @@ class MapStore {
const sorted = [...features];
switch (sortType) {
case "name_asc":
return sorted.sort((a, b) => a.name.localeCompare(b.name));
return sorted.sort((a, b) => a.name.trim().localeCompare(b.name.trim()));
case "name_desc":
return sorted.sort((a, b) => b.name.localeCompare(a.name));
return sorted.sort((a, b) => b.name.trim().localeCompare(a.name.trim()));
case "created_asc":
return sorted.sort((a, b) => {
if (
@@ -379,7 +379,7 @@ class MapStore {
}));
this.routes = this.routes.sort((a, b) =>
a.route_number.localeCompare(b.route_number),
a.route_number.trim().localeCompare(b.route_number.trim()),
);
await this.preloadRouteStations(routesIds);
@@ -2545,14 +2545,14 @@ const MapSightbar: React.FC<MapSightbarProps> = observer(
switch (sortType) {
case "name_asc":
return sorted.sort((a, b) =>
((a.get("name") as string) || "").localeCompare(
(b.get("name") as string) || "",
((a.get("name") as string) || "").trim().localeCompare(
((b.get("name") as string) || "").trim(),
),
);
case "name_desc":
return sorted.sort((a, b) =>
((b.get("name") as string) || "").localeCompare(
(a.get("name") as string) || "",
((b.get("name") as string) || "").trim().localeCompare(
((a.get("name") as string) || "").trim(),
),
);
case "created_asc":

View File

@@ -69,7 +69,7 @@ class MapStore {
path: route.path,
}));
this.routes = mappedRoutes.sort((a, b) =>
a.route_number.localeCompare(b.route_number)
a.route_number.trim().localeCompare(b.route_number.trim())
);
};

View File

@@ -97,7 +97,7 @@ export const MediaListPage = observer(() => {
];
const rows = useMemo(() => {
const query = searchQuery.toLowerCase();
const query = searchQuery.trim().toLowerCase();
return media
.filter((item) => !query || (item.media_name ?? "").toLowerCase().includes(query))
.map((item) => ({

View File

@@ -267,9 +267,9 @@ export const RouteCreatePage = observer(() => {
language as keyof typeof carrierStore.carriers
].data?.find((c: any) => c.id === carrier_id)?.full_name || "",
carrier_id,
route_number: routeNumber,
route_sys_number: govRouteNumber,
route_name: routeName,
route_number: routeNumber.trim(),
route_sys_number: govRouteNumber.trim(),
route_name: routeName.trim(),
route_direction,
scale_min: scale_min !== null ? scale_min : 0,
scale_max: scale_max !== null ? scale_max : 0,

View File

@@ -149,7 +149,7 @@ export const RouteListPage = observer(() => {
const rows = useMemo(() => {
const { selectedCityId } = selectedCityStore;
const query = searchQuery.toLowerCase();
const query = searchQuery.trim().toLowerCase();
let filtered = routes.data;
if (selectedCityId) {
const cityCarrierIds = new Set(

View File

@@ -122,7 +122,7 @@ export const SightListPage = observer(() => {
});
}, [sights, selectedCityStore.selectedCityId, canReadCities, authStore.meCities]);
const query = searchQuery.toLowerCase();
const query = searchQuery.trim().toLowerCase();
const rows = filteredSights
.filter((sight: any) => !query || (sight.name ?? "").toLowerCase().includes(query))
.map((sight) => ({

View File

@@ -91,7 +91,7 @@ export const SnapshotListPage = observer(() => {
];
const rows = useMemo(() => {
const query = searchQuery.toLowerCase();
const query = searchQuery.trim().toLowerCase();
return snapshots
.filter(
(snapshot) =>

View File

@@ -125,7 +125,7 @@ export const StationListPage = observer(() => {
const rows = useMemo(() => {
const { selectedCityId } = selectedCityStore;
const query = searchQuery.toLowerCase();
const query = searchQuery.trim().toLowerCase();
return stationLists[language].data
.filter((station: any) => !selectedCityId || station.city_id === selectedCityId)
.filter(

View File

@@ -109,7 +109,7 @@ export const UserListPage = observer(() => {
];
const rows = useMemo(() => {
const query = searchQuery.toLowerCase();
const query = searchQuery.trim().toLowerCase();
return (users.data ?? [])
.filter((user) =>
!query ||

View File

@@ -138,7 +138,7 @@ export const VehicleListPage = observer(() => {
];
const rows = useMemo(() => {
const query = searchQuery.toLowerCase();
const query = searchQuery.trim().toLowerCase();
return (vehicles.data ?? [])
.filter(
(vehicle) =>

View File

@@ -193,11 +193,11 @@ class CarrierStore {
const cityName = this.resolveCityName(this.createCarrierData.city_id, language);
const payload = {
full_name: this.createCarrierData[language].full_name,
short_name: this.createCarrierData[language].short_name,
full_name: (this.createCarrierData[language].full_name || "").trim(),
short_name: (this.createCarrierData[language].short_name || "").trim(),
city: cityName,
city_id: this.createCarrierData.city_id,
slogan: this.createCarrierData[language].slogan,
slogan: (this.createCarrierData[language].slogan || "").trim(),
...(this.createCarrierData.logo
? { logo: this.createCarrierData.logo }
: {}),
@@ -218,13 +218,13 @@ class CarrierStore {
);
const patchPayload = {
// @ts-ignore
full_name: this.createCarrierData[lang as any].full_name as string,
full_name: ((this.createCarrierData[lang as any].full_name as string) || "").trim(),
// @ts-ignore
short_name: this.createCarrierData[lang as any].short_name as string,
short_name: ((this.createCarrierData[lang as any].short_name as string) || "").trim(),
city: cityNameForLang || cityName,
city_id: this.createCarrierData.city_id,
// @ts-ignore
slogan: this.createCarrierData[lang as any].slogan as string,
slogan: ((this.createCarrierData[lang as any].slogan as string) || "").trim(),
...(this.createCarrierData.logo
? { logo: this.createCarrierData.logo }
: {}),
@@ -321,6 +321,9 @@ class CarrierStore {
const cityName = this.resolveCityName(this.editCarrierData.city_id, lang);
const response = await languageInstance(lang).patch(`/carrier/${id}`, {
...this.editCarrierData[lang],
full_name: (this.editCarrierData[lang].full_name || "").trim(),
short_name: (this.editCarrierData[lang].short_name || "").trim(),
slogan: (this.editCarrierData[lang].slogan || "").trim(),
city: cityName,
city_id: this.editCarrierData.city_id,
...(this.editCarrierData.logo

View File

@@ -171,7 +171,7 @@ class CityStore {
try {
// Create city in primary language
const cityPayload = {
name,
name: name.trim(),
country:
countryStore.countries[language as keyof CashedCountries]?.data.find(
(c) => c.code === country_code
@@ -200,7 +200,7 @@ class CityStore {
)?.name || "";
const patchPayload = {
name: secondaryName || "",
name: (secondaryName || "").trim(),
country: countryName,
country_code: country_code || "",
...(arms ? { arms } : {}),
@@ -285,7 +285,7 @@ class CityStore {
);
await languageInstance(language as Language).patch(`/city/${code}`, {
name,
name: (name || "").trim(),
country: country?.name || "",
country_code: country_code,
arms,

View File

@@ -136,7 +136,7 @@ class CountryStore {
if (code && this.createCountryData[language].name) {
await languageInstance(language as Language).post("/country", {
code: code,
name: name,
name: name.trim(),
});
runInAction(() => {
@@ -156,7 +156,7 @@ class CountryStore {
await languageInstance(secondaryLanguage as Language).patch(
`/country/${code}`,
{
name: name,
name: name.trim(),
}
);
}
@@ -212,7 +212,7 @@ class CountryStore {
if (name) {
await languageInstance(language as Language).patch(`/country/${code}`, {
name: name,
name: name.trim(),
});
runInAction(() => {

View File

@@ -493,7 +493,7 @@ class CreateSightStore {
latitude: this.sight.latitude,
longitude: this.sight.longitude,
is_default_icon: this.sight.is_default_icon,
name: this.sight[primaryLanguage].name,
name: (this.sight[primaryLanguage].name || "").trim(),
address: this.sight[primaryLanguage].address,
thumbnail: this.sight.thumbnail,
icon: this.sight.icon,
@@ -521,7 +521,7 @@ class CreateSightStore {
latitude: this.sight.latitude,
longitude: this.sight.longitude,
is_default_icon: this.sight.is_default_icon,
name: this.sight[lang].name,
name: (this.sight[lang].name || "").trim(),
address: this.sight[lang].address,
thumbnail: this.sight.thumbnail,
icon: this.sight.icon,

View File

@@ -299,9 +299,9 @@ class EditSightStore {
...this.sight.common,
translations: {
name: {
ru: this.sight.ru.name,
en: this.sight.en.name,
zh: this.sight.zh.name,
ru: (this.sight.ru.name || "").trim(),
en: (this.sight.en.name || "").trim(),
zh: (this.sight.zh.name || "").trim(),
},
address: {
ru: this.sight.ru.address,

View File

@@ -170,6 +170,9 @@ class RouteStore {
}
const dataToSend: any = {
...this.editRouteData,
route_name: (this.editRouteData.route_name || "").trim(),
route_number: (this.editRouteData.route_number || "").trim(),
route_sys_number: (this.editRouteData.route_sys_number || "").trim(),
center_latitude: parseFloat(this.editRouteData.center_latitude),
center_longitude: parseFloat(this.editRouteData.center_longitude),
};

View File

@@ -285,7 +285,7 @@ class SnapshotStore {
const response = await authInstance.post(
`/snapshots`,
{ name },
{ name: name.trim() },
{ headers: { "X-Request-ID": this.lastRequestId } }
);

View File

@@ -287,10 +287,10 @@ class StationsStore {
const response = await languageInstance(language).patch(
`/station/${id}`,
{
name: name || "",
system_name: name || "",
description: description || "",
address: address || "",
name: (name || "").trim(),
system_name: (name || "").trim(),
description: (description || "").trim(),
address: (address || "").trim(),
...commonDataPayload,
}
);
@@ -415,10 +415,10 @@ class StationsStore {
const { name, address } = this.createStationData[language];
const description = this.createStationData.common.description;
const response = await languageInstance(language).post("/station", {
name: name || "",
system_name: name || "",
description: description || "",
address: address || "",
name: (name || "").trim(),
system_name: (name || "").trim(),
description: (description || "").trim(),
address: (address || "").trim(),
...commonDataPayload,
});
@@ -436,10 +436,10 @@ class StationsStore {
const response = await languageInstance(lang).patch(
`/station/${stationId}`,
{
name: name || "",
system_name: name || "",
description: description || "",
address: address || "",
name: (name || "").trim(),
system_name: (name || "").trim(),
description: (description || "").trim(),
address: (address || "").trim(),
...commonDataPayload,
}
);

View File

@@ -92,7 +92,11 @@ class UserStore {
if (this.users.data.length > 0) {
id = this.users.data[this.users.data.length - 1].id + 1;
}
const payload: Partial<User> = { ...this.createUserData };
const payload: Partial<User> = {
...this.createUserData,
name: (this.createUserData.name || "").trim(),
email: (this.createUserData.email || "").trim(),
};
const baseRoles = new Set<string>(payload.roles ?? []);
baseRoles.add("articles_ro");
baseRoles.add("articles_rw");
@@ -141,7 +145,11 @@ class UserStore {
};
editUser = async (id: number) => {
const payload = { ...this.editUserData };
const payload = {
...this.editUserData,
name: (this.editUserData.name || "").trim(),
email: (this.editUserData.email || "").trim(),
};
if (!payload.icon) delete payload.icon;
if (!payload.password?.trim()) delete payload.password;

View File

@@ -122,9 +122,9 @@ class VehicleStore {
model?: string,
) => {
const payload: Record<string, unknown> = {
tail_number: tailNumber,
tail_number: tailNumber.trim(),
type,
carrier,
carrier: carrier.trim(),
carrier_id: carrierId,
};
// TODO: когда будет бекенд — добавить model в payload и в ответ
@@ -182,9 +182,9 @@ class VehicleStore {
},
) => {
const payload: Record<string, unknown> = {
tail_number: data.tail_number,
tail_number: data.tail_number.trim(),
type: data.type,
carrier: data.carrier,
carrier: data.carrier.trim(),
carrier_id: data.carrier_id,
};
if (data.model != null && data.model !== "") payload.model = data.model;

File diff suppressed because one or more lines are too long