proposal-system/api/src/ProposalSystem.Infrastructure/Services/SiteService.cs
Adam Moussa 9b502045dd Add site search, PO number, service category Other, and form enhancements
- Structured manual site entry with 5 separate address fields
- Site search via Autocomplete with server-side filtering
- Added PO number field to proposal form and AddPoNumber migration
- Added Other to ServiceCategory enum with custom category text input
- Label consistency: "Work Order #" → "Work Order Number", "PO Number"
- Top row reflow to 3-column layout (4/4/4)
- Dev PDF generation script for local testing
2026-05-27 18:17:48 -04:00

52 lines
1.5 KiB
C#

using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using ProposalSystem.Application.DTOs;
using ProposalSystem.Application.Interfaces;
namespace ProposalSystem.Infrastructure.Services;
public class SiteService : ISiteService
{
private readonly IAmazonDynamoDB _dynamo;
private const string TableName = "verified-sites";
public SiteService(IAmazonDynamoDB dynamo)
{
_dynamo = dynamo;
}
public async Task<IReadOnlyList<SiteResponse>> SearchAsync(string query, CancellationToken ct = default)
{
var upper = query.ToUpper();
var request = new ScanRequest
{
TableName = TableName,
FilterExpression = "contains(siteCode, :q)",
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
{ ":q", new AttributeValue { S = upper } }
},
Limit = 20,
};
var response = await _dynamo.ScanAsync(request, ct);
return response.Items
.Select(item => new SiteResponse(
GetString(item, "siteCode") ?? "",
GetString(item, "fullAddress"),
GetString(item, "address"),
GetString(item, "city"),
GetString(item, "state"),
GetString(item, "zip")
))
.OrderBy(s => s.SiteCode)
.ToList();
}
private static string? GetString(Dictionary<string, AttributeValue> item, string key)
{
return item.TryGetValue(key, out var attr) ? attr.S : null;
}
}