Skip to content

Commit

Permalink
chat 6/? I think
Browse files Browse the repository at this point in the history
  • Loading branch information
NielsPilgaard committed Aug 6, 2023
1 parent 35be69e commit ca59b74
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 6 deletions.
26 changes: 25 additions & 1 deletion src/web/Client/Features/Chat/UserAutoComplete.razor
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
<MudText>TODO: Place user search here</MudText>
@inject IUserSearchClient UserSearchClient


<MudAutocomplete T="string"
Label="Søg efter bruger"
@bind-Value="_searchString"
SearchFuncWithCancel="@SearchForUsers"
SelectValueOnTab
ShowProgressIndicator
OpenIcon="@string.Empty"
DebounceInterval="1000"
Clearable
MinCharacters="2" />


@code {

private string? _searchString;

private async Task<IEnumerable<string>> SearchForUsers(string arg1, CancellationToken arg2)
{
var searchResponse = await UserSearchClient.GetUsersWithAutoComplete(_searchString, arg2);

Check failure on line 22 in src/web/Client/Features/Chat/UserAutoComplete.razor

View workflow job for this annotation

GitHub Actions / test

No overload for method 'GetUsersWithAutoComplete' takes 2 arguments

Check failure on line 22 in src/web/Client/Features/Chat/UserAutoComplete.razor

View workflow job for this annotation

GitHub Actions / test

No overload for method 'GetUsersWithAutoComplete' takes 2 arguments

return searchResponse.IsSuccessStatusCode
? searchResponse.Content!.Select(response => response.ToString())
: Array.Empty<string>();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,4 @@
Location = value;
await LocationChanged.InvokeAsync(Location);
}

}
3 changes: 3 additions & 0 deletions src/web/Client/Features/UserSearch/IUserSearchClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@ public interface IUserSearchClient
{
[Get("/api/users/search")]
Task<IApiResponse<UserSearchResult>> GetUsers(UserSearchFilter filter);

[Get("/api/users/search/autocomplete")]
Task<IApiResponse<UserSearchResult>> GetUsersWithAutoComplete(string searchString);
}
17 changes: 17 additions & 0 deletions src/web/Server/Features/UserSearch/UserSearchApi.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Jordnaer.Server.Extensions;
using Jordnaer.Shared;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;

namespace Jordnaer.Server.Features.UserSearch;
Expand Down Expand Up @@ -45,6 +46,22 @@ public static RouteGroupBuilder MapUserSearch(this IEndpointRouteBuilder routes)
return users;
});


group.MapGet("autocomplete", async Task<Results<Ok<UserSearchResult>, BadRequest>> (
[FromServices] IUserSearchService userService,
[FromQuery] string searchString,
CancellationToken cancellationToken) =>
{
if (string.IsNullOrEmpty(searchString))
{
return TypedResults.BadRequest();
}
var users = await userService.GetUsersByNameAsync(searchString, cancellationToken);
return TypedResults.Ok(users);
});

return group;
}
}
41 changes: 37 additions & 4 deletions src/web/Server/Features/UserSearch/UserSearchService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ namespace Jordnaer.Server.Features.UserSearch;
public interface IUserSearchService
{
Task<UserSearchResult> GetUsersAsync(UserSearchFilter filter, CancellationToken cancellationToken);
Task<UserSearchResult> GetUsersByNameAsync(string searchString, CancellationToken cancellationToken);
}

public class UserSearchService : IUserSearchService
{
private static readonly List<string> _emptyStringList = new();
private static readonly List<ChildDto> _emptyChildDtoList = new();

private readonly ILogger<UserSearchService> _logger;
private readonly JordnaerDbContext _context;
private readonly IDataForsyningenClient _dataForsyningenClient;
Expand All @@ -30,13 +34,42 @@ public UserSearchService(
_options = options.Value;
}

public async Task<UserSearchResult> GetUsersByNameAsync(string searchString, CancellationToken cancellationToken)
{

var users = _context.UserProfiles.AsQueryable();

users = ApplyNameFilter(searchString, users);

var paginatedUsers = await users
.OrderBy(user => user.CreatedUtc)
.Take(10)
.Select(user => new UserDto
{
ProfilePictureUrl = user.ProfilePictureUrl,
UserName = user.UserName,
FirstName = user.FirstName,
LastName = user.LastName,
ZipCode = user.ZipCode,
City = user.City,
Children = _emptyChildDtoList,
LookingFor = _emptyStringList
})
.AsNoTracking()
.ToListAsync(cancellationToken);

int totalCount = await users.AsNoTracking().CountAsync(cancellationToken);

return new UserSearchResult { TotalCount = totalCount, Users = paginatedUsers };
}

public async Task<UserSearchResult> GetUsersAsync(UserSearchFilter filter, CancellationToken cancellationToken)
{
// TODO: Convert to Dapper
var users = _context.UserProfiles.AsQueryable();

users = ApplyChildFilters(filter, users);
users = ApplyNameFilter(filter, users);
users = ApplyNameFilter(filter.Name, users);
users = ApplyLookingForFilter(filter, users);
(users, bool isOrdered) = await ApplyLocationFilterAsync(filter, users);

Expand Down Expand Up @@ -152,11 +185,11 @@ private static IQueryable<UserProfile> ApplyLookingForFilter(UserSearchFilter fi
return users;
}

private static IQueryable<UserProfile> ApplyNameFilter(UserSearchFilter filter, IQueryable<UserProfile> users)
private static IQueryable<UserProfile> ApplyNameFilter(string? filter, IQueryable<UserProfile> users)
{
if (!string.IsNullOrWhiteSpace(filter.Name))
if (!string.IsNullOrWhiteSpace(filter))
{
string trimmedNameFilter = new(filter.Name.Where(c => !char.IsWhiteSpace(c)).ToArray());
string trimmedNameFilter = new(filter.Where(c => !char.IsWhiteSpace(c)).ToArray());

users = users.Where(user => !string.IsNullOrEmpty(user.SearchableName) &&
EF.Functions.Like(user.SearchableName, $"%{trimmedNameFilter}%"));
Expand Down

0 comments on commit ca59b74

Please sign in to comment.