counties, pagination, filter count, show total results
This commit is contained in:
File diff suppressed because it is too large
Load Diff
63211
bizmatch-server/src/assets/counties_raw.csv
Normal file
63211
bizmatch-server/src/assets/counties_raw.csv
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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[];
|
||||
}
|
||||
|
||||
@@ -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`);
|
||||
|
||||
68
bizmatch-server/src/utils/importCounties.ts
Normal file
68
bizmatch-server/src/utils/importCounties.ts
Normal 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));
|
||||
Reference in New Issue
Block a user