counties, pagination, filter count, show total results

This commit is contained in:
2024-07-19 18:06:56 +02:00
parent abcde3991d
commit 9db23c2177
25 changed files with 67207 additions and 509 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,23 @@
import { Controller, Get, Param } from '@nestjs/common';
import { Body, Controller, Get, Param, Post } from '@nestjs/common';
import { CountyRequest } from 'src/models/server.model.js';
import { GeoService } from './geo.service.js';
@Controller('geo')
export class GeoController {
constructor(private geoService:GeoService){}
@Get(':prefix')
findByPrefix(@Param('prefix') prefix:string): any {
return this.geoService.findCitiesStartingWith(prefix);
}
constructor(private geoService: GeoService) {}
@Get(':prefix/:state')
findByPrefixAndState(@Param('prefix') prefix:string,@Param('state') state:string): any {
return this.geoService.findCitiesStartingWith(prefix,state);
}
@Get(':prefix')
findByPrefix(@Param('prefix') prefix: string): any {
return this.geoService.findCitiesStartingWith(prefix);
}
@Get(':prefix/:state')
findByPrefixAndState(@Param('prefix') prefix: string, @Param('state') state: string): any {
return this.geoService.findCitiesStartingWith(prefix, state);
}
@Post('counties')
findByPrefixAndStates(@Body() countyRequest: CountyRequest): any {
return this.geoService.findCountiesStartingWith(countyRequest.prefix, countyRequest.states);
}
}

View File

@@ -1,9 +1,9 @@
import { Injectable } from '@nestjs/common';
import { readFileSync } from 'fs';
import path, { join } from 'path';
import { GeoResult } from 'src/models/main.model.js';
import { CountyResult, GeoResult } from 'src/models/main.model.js';
import { fileURLToPath } from 'url';
import { City, Geo, State } from '../models/server.model.js';
import { City, CountyData, Geo, State } from '../models/server.model.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
@@ -11,6 +11,7 @@ const __dirname = path.dirname(__filename);
@Injectable()
export class GeoService {
geo: Geo;
counties: CountyData[];
constructor() {
this.loadGeo();
}
@@ -18,9 +19,32 @@ export class GeoService {
const filePath = join(__dirname, '../..', 'assets', 'geo.json');
const rawData = readFileSync(filePath, 'utf8');
this.geo = JSON.parse(rawData);
const countiesFilePath = join(__dirname, '../..', 'assets', 'counties.json');
const rawCountiesData = readFileSync(countiesFilePath, 'utf8');
this.counties = JSON.parse(rawCountiesData);
}
findCountiesStartingWith(prefix: string, states?: string[]) {
let results: CountyResult[] = [];
let idCounter = 1;
findCitiesStartingWith(prefix: string, state?: string): { city: string; state: string; state_code: string }[] {
this.counties.forEach(stateData => {
if (!states || states.includes(stateData.state)) {
stateData.counties.forEach(county => {
if (county.startsWith(prefix.toUpperCase())) {
results.push({
id: idCounter++,
name: county,
state: stateData.state_full,
state_code: stateData.state,
});
}
});
}
});
return results;
}
findCitiesStartingWith(prefix: string, state?: string): GeoResult[] {
const result: GeoResult[] = [];
this.geo.states.forEach((state: State) => {

View File

@@ -29,7 +29,10 @@ export class BusinessListingsController {
find(@Request() req, @Body() criteria: BusinessListingCriteria): any {
return this.listingsService.searchBusinessListings(criteria, req.user as JwtUser);
}
@Post('findTotal')
findTotal(@Body() criteria: BusinessListingCriteria): Promise<number> {
return this.listingsService.getBusinessListingsCount(criteria);
}
// @UseGuards(OptionalJwtAuthGuard)
// @Post('search')
// search(@Request() req, @Body() criteria: BusinessListingCriteria): any {

View File

@@ -31,6 +31,10 @@ export class CommercialPropertyListingsController {
async find(@Request() req, @Body() criteria: CommercialPropertyListingCriteria): Promise<any> {
return await this.listingsService.searchCommercialProperties(criteria, req.user as JwtUser);
}
@Post('findTotal')
findTotal(@Body() criteria: CommercialPropertyListingCriteria): Promise<number> {
return this.listingsService.getCommercialPropertiesCount(criteria);
}
@Get('states/all')
getStates(): any {
return this.listingsService.getStates();

View File

@@ -57,7 +57,6 @@ export interface ListCriteria {
start: number;
length: number;
page: number;
pageCount: number;
types: string[];
city: string;
prompt: string;
@@ -230,6 +229,12 @@ export interface GeoResult {
state: string;
state_code: string;
}
export interface CountyResult {
id: number;
name: string;
state: string;
state_code: string;
}
export function isEmpty(value: any): boolean {
// Check for undefined or null
if (value === undefined || value === null) {

View File

@@ -61,3 +61,12 @@ export interface Timezone {
abbreviation: string;
tzName: string;
}
export interface CountyData {
state: string;
state_full: string;
counties: string[];
}
export interface CountyRequest {
prefix: string;
states: string[];
}

View File

@@ -45,6 +45,10 @@ export class UserController {
this.logger.info(`Found users: ${JSON.stringify(foundUsers)}`);
return foundUsers;
}
@Post('findTotal')
findTotal(@Body() criteria: UserListingCriteria): Promise<number> {
return this.userService.getUserListingsCount(criteria);
}
@Get('states/all')
async getStates(): Promise<any[]> {
this.logger.info(`Getting all states for users`);

View File

@@ -0,0 +1,68 @@
import * as fs from 'fs';
import * as readline from 'readline';
interface CityData {
city: string;
stateShort: string;
stateFull: string;
county: string;
cityAlias: string;
}
interface StateCountyData {
state: string;
state_full: string;
counties: string[];
}
async function parseData(filePath: string): Promise<CityData[]> {
const fileStream = fs.createReadStream(filePath);
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity,
});
const data: CityData[] = [];
let isFirstLine = true;
for await (const line of rl) {
if (isFirstLine) {
isFirstLine = false;
continue; // Skip the first line
}
const [city, stateShort, stateFull, county, cityAlias] = line.split('|');
data.push({ city, stateShort, stateFull, county, cityAlias });
}
return data;
}
function transformData(data: CityData[]): StateCountyData[] {
const stateMap: { [key: string]: { stateFull: string; counties: Set<string> } } = {};
data.forEach(item => {
if (!stateMap[item.stateShort]) {
stateMap[item.stateShort] = {
stateFull: item.stateFull,
counties: new Set(),
};
}
stateMap[item.stateShort].counties.add(item.county);
});
return Object.entries(stateMap).map(([state, value]) => ({
state,
state_full: value.stateFull,
counties: Array.from(value.counties).sort(),
}));
}
async function main() {
const filePath = './src/assets/counties_raw.csv'; // Ersetze diesen Pfad mit dem Pfad zu deiner Datei
const cityData = await parseData(filePath);
const stateCountyData = transformData(cityData);
console.log(JSON.stringify(stateCountyData, null, 2));
}
main().catch(err => console.error(err));