From 69de9a3a051e4541a61f44dfdd3a65896c9edbf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Qu=E1=BB=91c=20B=E1=BA=A3o=20An?= Date: Mon, 29 Jun 2026 09:32:04 -0400 Subject: [PATCH] feat: Add StateService in order to standardize states (ex: GA -> Georgia) --- .../Controllers/InstitutionController.cs | 21 +- LostFound_API/DTOs/States/StatesDTO.cs | 12 + LostFound_API/Program.cs | 4 + LostFound_API/Resources/States.json | 206 ++++++++++++++++++ LostFound_API/Services/StateService.cs | 49 +++++ 5 files changed, 286 insertions(+), 6 deletions(-) create mode 100644 LostFound_API/DTOs/States/StatesDTO.cs create mode 100644 LostFound_API/Resources/States.json create mode 100644 LostFound_API/Services/StateService.cs diff --git a/LostFound_API/Controllers/InstitutionController.cs b/LostFound_API/Controllers/InstitutionController.cs index e46b4d7..5d02bf2 100644 --- a/LostFound_API/Controllers/InstitutionController.cs +++ b/LostFound_API/Controllers/InstitutionController.cs @@ -1,6 +1,7 @@ using Azure; using LostFound_API.DTOs.Institution; using LostFound_API.DTOs.Users; +using LostFound_API.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using ObjectBusiness; @@ -18,31 +19,39 @@ public class InstitutionController : ControllerBase { #region Variables private readonly IInstitutionRepository institutionRepository; - private readonly IWebHostEnvironment webHost; + private readonly StateService stateService; private readonly IConfiguration configuration; private readonly IHttpClientFactory httpClientFactory; #endregion #region Constructor public InstitutionController(IInstitutionRepository institutionRepository, - IWebHostEnvironment webHost, + StateService stateService, IConfiguration configuration, IHttpClientFactory httpClientFactory) { this.institutionRepository = institutionRepository; - this.webHost = webHost; + this.stateService = stateService; this.configuration = configuration; this.httpClientFactory = httpClientFactory; } #endregion - // GET: api/ [HttpGet] - public IEnumerable Get() + public IActionResult Test() { - return new string[] { "value1", "value2" }; + var state = stateService.ByCode["GA"]; + + return Ok(state.Name); } + // GET: api/ + //[HttpGet] + //public IEnumerable Get() + //{ + // return new string[] { "value1", "value2" }; + //} + // GET api//5 [HttpGet("search")] public async Task Search(string query) diff --git a/LostFound_API/DTOs/States/StatesDTO.cs b/LostFound_API/DTOs/States/StatesDTO.cs new file mode 100644 index 0000000..9b67db2 --- /dev/null +++ b/LostFound_API/DTOs/States/StatesDTO.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; + +namespace LostFound_API.DTOs.States +{ + public class StatesDTO + { + [JsonPropertyName("code")] + public string Code { get; set; } + [JsonPropertyName("name")] + public string Name { get; set; } + } +} diff --git a/LostFound_API/Program.cs b/LostFound_API/Program.cs index e8fbf5d..7e9d1f2 100644 --- a/LostFound_API/Program.cs +++ b/LostFound_API/Program.cs @@ -4,6 +4,7 @@ using LostFound_API.DTOs.Posts; using LostFound_API.DTOs.Users; using LostFound_API.DTOs.VerificationCodes; +using LostFound_API.Services; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; @@ -80,6 +81,9 @@ }; }); +// Add singleton state service one time +builder.Services.AddSingleton(); + // Add SignalR builder.Services.AddSignalR() //.AddAzureSignalR() // Use azure signalR service diff --git a/LostFound_API/Resources/States.json b/LostFound_API/Resources/States.json new file mode 100644 index 0000000..849f180 --- /dev/null +++ b/LostFound_API/Resources/States.json @@ -0,0 +1,206 @@ +[ + { + "code": "AL", + "name": "Alabama" + }, + { + "code": "AK", + "name": "Alaska" + }, + { + "code": "AZ", + "name": "Arizona" + }, + { + "code": "AR", + "name": "Arkansas" + }, + { + "code": "CA", + "name": "California" + }, + { + "code": "CO", + "name": "Colorado" + }, + { + "code": "CT", + "name": "Connecticut" + }, + { + "code": "DE", + "name": "Delaware" + }, + { + "code": "FL", + "name": "Florida" + }, + { + "code": "GA", + "name": "Georgia" + }, + { + "code": "HI", + "name": "Hawaii" + }, + { + "code": "ID", + "name": "Idaho" + }, + { + "code": "IL", + "name": "Illinois" + }, + { + "code": "IN", + "name": "Indiana" + }, + { + "code": "IA", + "name": "Iowa" + }, + { + "code": "KS", + "name": "Kansas" + }, + { + "code": "KY", + "name": "Kentucky" + }, + { + "code": "LA", + "name": "Louisiana" + }, + { + "code": "ME", + "name": "Maine" + }, + { + "code": "MD", + "name": "Maryland" + }, + { + "code": "MA", + "name": "Massachusetts" + }, + { + "code": "MI", + "name": "Michigan" + }, + { + "code": "MN", + "name": "Minnesota" + }, + { + "code": "MS", + "name": "Mississippi" + }, + { + "code": "MO", + "name": "Missouri" + }, + { + "code": "MT", + "name": "Montana" + }, + { + "code": "NE", + "name": "Nebraska" + }, + { + "code": "NV", + "name": "Nevada" + }, + { + "code": "NH", + "name": "New Hampshire" + }, + { + "code": "NJ", + "name": "New Jersey" + }, + { + "code": "NM", + "name": "New Mexico" + }, + { + "code": "NY", + "name": "New York" + }, + { + "code": "NC", + "name": "North Carolina" + }, + { + "code": "ND", + "name": "North Dakota" + }, + { + "code": "OH", + "name": "Ohio" + }, + { + "code": "OK", + "name": "Oklahoma" + }, + { + "code": "OR", + "name": "Oregon" + }, + { + "code": "PA", + "name": "Pennsylvania" + }, + { + "code": "RI", + "name": "Rhode Island" + }, + { + "code": "SC", + "name": "South Carolina" + }, + { + "code": "SD", + "name": "South Dakota" + }, + { + "code": "TN", + "name": "Tennessee" + }, + { + "code": "TX", + "name": "Texas" + }, + { + "code": "UT", + "name": "Utah" + }, + { + "code": "VT", + "name": "Vermont" + }, + { + "code": "VA", + "name": "Virginia" + }, + { + "code": "WA", + "name": "Washington" + }, + { + "code": "WV", + "name": "West Virginia" + }, + { + "code": "WI", + "name": "Wisconsin" + }, + { + "code": "WY", + "name": "Wyoming" + }, + { + "code": "DC", + "name": "Washington, D.C." + } +] \ No newline at end of file diff --git a/LostFound_API/Services/StateService.cs b/LostFound_API/Services/StateService.cs new file mode 100644 index 0000000..909333f --- /dev/null +++ b/LostFound_API/Services/StateService.cs @@ -0,0 +1,49 @@ +using LostFound_API.DTOs.States; +using System.Text.Json; + +namespace LostFound_API.Services +{ + public class StateService + { + public IReadOnlyDictionary ByCode { get; set; } + public IReadOnlyDictionary ByName { get; set; } + + public StateService(IWebHostEnvironment webHostEnvironment) + { + // Build the full file path to the JSON file + // ContentRootPath = root directory of the application + var path = Path.Combine( + webHostEnvironment.ContentRootPath, + "Resources", + "States.json" + ); + + // Read the entire JSON file into a string + var json = File.ReadAllText(path); + + // Deserialize JSON into a List of State DTO objects + // Example JSON: + // [{ "code": "GA", "name": "Georgia" }, ...] + var states = JsonSerializer.Deserialize>(json) ?? new List(); + + // Create a dictionary for fast lookup by state code + // Key: state code (e.g. "GA", "CA") + // Value: StatesDTO object + // StringComparer.OrdinalIgnoreCase makes it case-insensitive + // so "ga" and "GA" are treated the same + ByCode = states.ToDictionary( + x => x.Code, + StringComparer.OrdinalIgnoreCase + ); + + // Create a dictionary for fast lookup by state name + // Key: state name (e.g. "Georgia", "California") + // Value: StatesDTO object + // Also case-insensitive for flexible search + ByName = states.ToDictionary( + x => x.Name, + StringComparer.OrdinalIgnoreCase + ); + } + } +}