initial commit

This commit is contained in:
2026-03-20 23:52:10 +01:00
parent 05bea695bd
commit ce04cd8d77
38 changed files with 3006 additions and 52 deletions

View File

@@ -0,0 +1,101 @@
using CityInfo.API.DbContexts;
using CityInfo.API.Entities;
using Microsoft.EntityFrameworkCore;
namespace CityInfo.API.Services
{
public class CityInfoRepository : ICityInfoRepository
{
private CityInfoContext _context;
public CityInfoRepository(CityInfoContext context)
{
_context = context ?? throw new ArgumentNullException(nameof(CityInfoContext));
}
public async Task<IEnumerable<City>> GetCitiesAsync()
{
return await _context.Cities.OrderBy((city) => city.Name).ToListAsync();
}
public async Task<(IEnumerable<City>, PaginationMetadata)> GetCitiesAsync(string? name, string? searchQuery, int pageNumber, int pageSize)
{
var collection = _context.Cities as IQueryable<City>;
if (!string.IsNullOrEmpty(name))
{
name = name.Trim();
collection = collection.Where((city) => city.Name == name);
}
if (!string.IsNullOrEmpty(searchQuery))
{
searchQuery = searchQuery.Trim();
collection = collection.Where(
(city) => (
city.Name.Contains(searchQuery) |
(city.Description != null && city.Description.Contains(searchQuery))
)
);
}
var totalItemCount = await collection.CountAsync();
var paginationMetaData = new PaginationMetadata(totalItemCount, pageSize, pageNumber);
var collectionToReturn = await collection
.OrderBy((city) => city.Name)
.Skip(pageSize * (pageNumber - 1))
.Take(pageSize)
.ToListAsync();
return (collectionToReturn, paginationMetaData);
}
public async Task<City?> GetCityAsync(int cityId, bool includePointsOfinterest)
{
if (includePointsOfinterest)
{
return await _context.Cities
.Include((city) => city.PointsOfInterest)
.Where((city) => city.Id == cityId)
.FirstOrDefaultAsync();
}
return await _context.Cities
.Where((city) => city.Id == cityId)
.FirstOrDefaultAsync();
}
public async Task<bool> CityExistAsync(int cityId)
{
return await _context.Cities.AnyAsync((city) => city.Id == cityId);
}
public async Task<IEnumerable<PointOfInterest>> GetPointsOfinterestForCityAsync(int cityId)
{
return await _context.PointsOfInterest.Where((poi) => poi.CityId == cityId).ToListAsync();
}
public async Task<PointOfInterest?> GetPointOfInterestForCityAsync(int cityId, int pointOfInterestId)
{
return await _context.PointsOfInterest.Where((poi) => poi.CityId == cityId && poi.Id == pointOfInterestId).FirstOrDefaultAsync();
}
public async Task CreatePointOfInterestForCityAsync(int cityId, PointOfInterest pointOfInterest)
{
var city = await GetCityAsync(cityId, includePointsOfinterest: false);
if (city != null)
{
city.PointsOfInterest.Add(pointOfInterest);
}
}
public async Task<bool> SaveChangesAsync()
{
return (await _context.SaveChangesAsync() >= 0);
}
public void DeletePointOfInterest(PointOfInterest pointOfInterest)
{
_context.PointsOfInterest.Remove(pointOfInterest);
}
public async Task<bool> CityNameMatchesCityId(string? cityName, int cityId)
{
return await _context.Cities.AnyAsync((city) => city.Name == cityName && city.Id == cityId);
}
}
}

View File

@@ -0,0 +1,20 @@
namespace CityInfo.API.Services
{
public class CloudMailService : IMailService
{
private string _mailTo = string.Empty;
private string _mailFrom = string.Empty;
public CloudMailService(
IConfiguration configuration)
{
_mailTo = configuration["mailsettings:mailToAddress"];
_mailFrom = configuration["mailsettings:mailFromAddress"];
}
public void Send(string subject, string message)
{
Console.WriteLine($"Mail from {_mailFrom} to {_mailTo} with {nameof(CloudMailService)}");
Console.WriteLine($"Subject: {subject}");
Console.WriteLine($"Message: {message}");
}
}
}

View File

@@ -0,0 +1,18 @@
using CityInfo.API.Entities;
namespace CityInfo.API.Services
{
public interface ICityInfoRepository
{
Task<IEnumerable<City>> GetCitiesAsync();
Task<(IEnumerable<City>, PaginationMetadata)> GetCitiesAsync(string? name, string? searchQuery, int pageNumber, int pageSize);
Task<City?> GetCityAsync(int cityId, bool includePointsOfinterest);
Task<bool> CityExistAsync(int cityId);
Task<IEnumerable<PointOfInterest>> GetPointsOfinterestForCityAsync(int cityId);
Task<PointOfInterest?> GetPointOfInterestForCityAsync(int cityId, int pointOfInterestId);
Task CreatePointOfInterestForCityAsync(int cityId, PointOfInterest pointOfInterest);
void DeletePointOfInterest(PointOfInterest pointOfInterest);
Task<bool> CityNameMatchesCityId(string? cityName, int cityId);
Task<bool> SaveChangesAsync();
}
}

View File

@@ -0,0 +1,7 @@
namespace CityInfo.API.Services
{
public interface IMailService
{
public void Send(string subject, string message);
}
}

View File

@@ -0,0 +1,21 @@
namespace CityInfo.API.Services
{
public class LocalMailService:IMailService
{
private string _mailTo = string.Empty;
private string _mailFrom = string.Empty;
public LocalMailService(
IConfiguration configuration)
{
_mailTo = configuration["mailsettings:mailToAddress"];
_mailFrom = configuration["mailsettings:mailFromAddress"];
}
public void Send(string subject, string message)
{
Console.WriteLine($"Mail from {_mailFrom} to {_mailTo} with {nameof(LocalMailService)}");
Console.WriteLine($"Subject: {subject}");
Console.WriteLine($"Message: {message}");
}
}
}

View File

@@ -0,0 +1,18 @@
namespace CityInfo.API.Services
{
public class PaginationMetadata
{
public int TotalItemCount { get; set; }
public int TotalPageCount { get; set; }
public int PageSize { get; set; }
public int CurrentPage { get; set; }
public PaginationMetadata(int totalItemCount, int pageSize, int currentPage)
{
TotalItemCount = totalItemCount;
PageSize = pageSize;
CurrentPage = currentPage;
TotalPageCount = (int)Math.Ceiling(totalItemCount / (double)pageSize);
}
}
}