'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.' ); } } ); }