284 lines
8.5 KiB
TypeScript
284 lines
8.5 KiB
TypeScript
'use server';
|
|
|
|
import { getInjection } from '@/di/container';
|
|
import db from '@/prisma/db';
|
|
import {
|
|
AuthenticationError,
|
|
UnauthenticatedError,
|
|
} from '@/src/entities/errors/auth';
|
|
import { InputParseError } from '@/src/entities/errors/common';
|
|
|
|
export async function getAvailableYears() {
|
|
const instrumentationService = getInjection('IInstrumentationService');
|
|
return await instrumentationService.instrumentServerAction(
|
|
'Available Years',
|
|
{ recordResponse: true },
|
|
async () => {
|
|
try {
|
|
const years = await db.crimes.findMany({
|
|
select: {
|
|
year: true,
|
|
},
|
|
distinct: ['year'],
|
|
orderBy: {
|
|
year: 'asc',
|
|
},
|
|
});
|
|
|
|
return years.map((year) => year.year);
|
|
} catch (err) {
|
|
if (err instanceof InputParseError) {
|
|
// return {
|
|
// error: err.message,
|
|
// };
|
|
|
|
throw new InputParseError(err.message);
|
|
}
|
|
|
|
if (err instanceof AuthenticationError) {
|
|
// return {
|
|
// error: 'User not found.',
|
|
// };
|
|
|
|
throw new AuthenticationError(
|
|
'There was an error with the credentials. Please try again or contact support.'
|
|
);
|
|
}
|
|
|
|
const crashReporterService = getInjection('ICrashReporterService');
|
|
crashReporterService.report(err);
|
|
// return {
|
|
// error:
|
|
// 'An error happened. The developers have been notified. Please try again later.',
|
|
// };
|
|
throw new Error(
|
|
'An error happened. The developers have been notified. Please try again later.'
|
|
);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
export async function getCrimes() {
|
|
const instrumentationService = getInjection('IInstrumentationService');
|
|
return await instrumentationService.instrumentServerAction(
|
|
'District Crime Data',
|
|
{ recordResponse: true },
|
|
async () => {
|
|
try {
|
|
const crimes = await db.crimes.findMany({
|
|
include: {
|
|
districts: {
|
|
select: {
|
|
name: true,
|
|
},
|
|
},
|
|
crime_incidents: {
|
|
select: {
|
|
timestamp: true,
|
|
description: true,
|
|
status: true,
|
|
crime_categories: {
|
|
select: {
|
|
name: true,
|
|
type: true,
|
|
},
|
|
},
|
|
locations: {
|
|
select: {
|
|
address: true,
|
|
latitude: true,
|
|
longitude: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
return crimes.map((crime) => {
|
|
return {
|
|
id: crime.id,
|
|
district: crime.districts.name,
|
|
number_of_crime: crime.number_of_crime,
|
|
level: crime.level,
|
|
score: crime.score,
|
|
month: crime.month,
|
|
year: crime.year,
|
|
incidents: crime.crime_incidents.map((incident) => {
|
|
return {
|
|
timestamp: incident.timestamp,
|
|
description: incident.description,
|
|
status: incident.status,
|
|
category: incident.crime_categories.name,
|
|
type: incident.crime_categories.type,
|
|
address: incident.locations.address,
|
|
latitude: incident.locations.latitude,
|
|
longitude: incident.locations.longitude,
|
|
};
|
|
}),
|
|
};
|
|
});
|
|
} catch (err) {
|
|
if (err instanceof InputParseError) {
|
|
// return {
|
|
// error: err.message,
|
|
// };
|
|
|
|
throw new InputParseError(err.message);
|
|
}
|
|
|
|
if (err instanceof AuthenticationError) {
|
|
// return {
|
|
// error: 'User not found.',
|
|
// };
|
|
|
|
throw new AuthenticationError(
|
|
'There was an error with the credentials. Please try again or contact support.'
|
|
);
|
|
}
|
|
|
|
const crashReporterService = getInjection('ICrashReporterService');
|
|
crashReporterService.report(err);
|
|
// return {
|
|
// error:
|
|
// 'An error happened. The developers have been notified. Please try again later.',
|
|
// };
|
|
throw new Error(
|
|
'An error happened. The developers have been notified. Please try again later.'
|
|
);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
export async function getCrimeByYearAndMonth(
|
|
year: number,
|
|
month: number | 'all'
|
|
) {
|
|
const instrumentationService = getInjection('IInstrumentationService');
|
|
return await instrumentationService.instrumentServerAction(
|
|
'District Crime Data',
|
|
{ recordResponse: true },
|
|
async () => {
|
|
try {
|
|
// Build where clause conditionally based on provided parameters
|
|
const whereClause: any = {
|
|
year: year, // Always filter by year now since "all" is removed
|
|
};
|
|
|
|
// Only add month to filter if it's not "all"
|
|
if (month !== 'all') {
|
|
whereClause.month = month;
|
|
}
|
|
|
|
const crimes = await db.crimes.findMany({
|
|
where: whereClause,
|
|
include: {
|
|
districts: {
|
|
select: {
|
|
name: true,
|
|
geographics: {
|
|
where: { year }, // Match geographics to selected year
|
|
select: {
|
|
address: true,
|
|
land_area: true,
|
|
year: true,
|
|
},
|
|
},
|
|
demographics: {
|
|
where: { year }, // Match demographics to selected year
|
|
select: {
|
|
number_of_unemployed: true,
|
|
population: true,
|
|
population_density: true,
|
|
year: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
crime_incidents: {
|
|
select: {
|
|
id: true,
|
|
timestamp: true,
|
|
description: true,
|
|
status: true,
|
|
crime_categories: {
|
|
select: {
|
|
name: true,
|
|
type: true,
|
|
},
|
|
},
|
|
locations: {
|
|
select: {
|
|
address: true,
|
|
latitude: true,
|
|
longitude: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
return crimes.map((crime) => {
|
|
return {
|
|
id: crime.id,
|
|
distrcit_id: crime.district_id,
|
|
district_name: crime.districts.name,
|
|
number_of_crime: crime.number_of_crime,
|
|
level: crime.level,
|
|
score: crime.score,
|
|
month: crime.month,
|
|
year: crime.year,
|
|
geographics: crime.districts.geographics.map((geo) => {
|
|
return {
|
|
address: geo.address,
|
|
land_area: geo.land_area,
|
|
year: geo.year,
|
|
};
|
|
}),
|
|
demographics: crime.districts.demographics.map((demo) => {
|
|
return {
|
|
number_of_unemployed: demo.number_of_unemployed,
|
|
population: demo.population,
|
|
population_density: demo.population_density,
|
|
year: demo.year,
|
|
};
|
|
}),
|
|
incidents: crime.crime_incidents.map((incident) => {
|
|
return {
|
|
id: incident.id,
|
|
timestamp: incident.timestamp,
|
|
description: incident.description,
|
|
status: incident.status,
|
|
category: incident.crime_categories.name,
|
|
type: incident.crime_categories.type,
|
|
address: incident.locations.address,
|
|
latitude: incident.locations.latitude,
|
|
longitude: incident.locations.longitude,
|
|
};
|
|
}),
|
|
};
|
|
});
|
|
} catch (err) {
|
|
if (err instanceof InputParseError) {
|
|
throw new InputParseError(err.message);
|
|
}
|
|
|
|
if (err instanceof AuthenticationError) {
|
|
throw new AuthenticationError(
|
|
'There was an error with the credentials. Please try again or contact support.'
|
|
);
|
|
}
|
|
|
|
const crashReporterService = getInjection('ICrashReporterService');
|
|
crashReporterService.report(err);
|
|
throw new Error(
|
|
'An error happened. The developers have been notified. Please try again later.'
|
|
);
|
|
}
|
|
}
|
|
);
|
|
}
|