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 rows = useMemo(() => {
const query = searchQuery.toLowerCase(); const query = searchQuery.trim().toLowerCase();
return articleList[language].data return articleList[language].data
.filter((article) => !query || (article.heading ?? "").toLowerCase().includes(query)) .filter((article) => !query || (article.heading ?? "").toLowerCase().includes(query))
.map((article) => ({ .map((article) => ({

View File

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

View File

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

View File

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

View File

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

View File

@@ -69,7 +69,7 @@ class MapStore {
path: route.path, path: route.path,
})); }));
this.routes = mappedRoutes.sort((a, b) => 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 rows = useMemo(() => {
const query = searchQuery.toLowerCase(); const query = searchQuery.trim().toLowerCase();
return media return media
.filter((item) => !query || (item.media_name ?? "").toLowerCase().includes(query)) .filter((item) => !query || (item.media_name ?? "").toLowerCase().includes(query))
.map((item) => ({ .map((item) => ({

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -170,6 +170,9 @@ class RouteStore {
} }
const dataToSend: any = { const dataToSend: any = {
...this.editRouteData, ...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_latitude: parseFloat(this.editRouteData.center_latitude),
center_longitude: parseFloat(this.editRouteData.center_longitude), center_longitude: parseFloat(this.editRouteData.center_longitude),
}; };

View File

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

View File

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

View File

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

View File

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

File diff suppressed because one or more lines are too long