Adding dialog for checking new number
This commit is contained in:
parent
e5afc6dbdc
commit
b2f5aee4e7
@ -25,6 +25,7 @@ public partial class App : Application
|
|||||||
services.AddTransient<HistoryViewModel>();
|
services.AddTransient<HistoryViewModel>();
|
||||||
services.AddTransient<AuthWindowViewModel>();
|
services.AddTransient<AuthWindowViewModel>();
|
||||||
services.AddTransient<MainWindowViewModel>();
|
services.AddTransient<MainWindowViewModel>();
|
||||||
|
services.AddTransient<CheckNumberViewModel>();
|
||||||
|
|
||||||
// Windows
|
// Windows
|
||||||
services.AddWindowFactory<AuthWindow>();
|
services.AddWindowFactory<AuthWindow>();
|
||||||
|
|||||||
21
AutoCat/Utils/Alerts.cs
Normal file
21
AutoCat/Utils/Alerts.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using MsBox.Avalonia;
|
||||||
|
using MsBox.Avalonia.Dto;
|
||||||
|
using MsBox.Avalonia.Enums;
|
||||||
|
|
||||||
|
namespace AutoCat.Utils;
|
||||||
|
|
||||||
|
public class Alerts
|
||||||
|
{
|
||||||
|
public static async void ShowError(Exception error)
|
||||||
|
{
|
||||||
|
var msgBox = MessageBoxManager.GetMessageBoxStandard(new MessageBoxStandardParams
|
||||||
|
{
|
||||||
|
ButtonDefinitions = ButtonEnum.Ok,
|
||||||
|
ContentTitle = "Error",
|
||||||
|
ContentMessage = error.Message
|
||||||
|
});
|
||||||
|
|
||||||
|
await msgBox.ShowAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using AutoCat.Utils;
|
||||||
using AutoCatCore.Services.Api;
|
using AutoCatCore.Services.Api;
|
||||||
using AutoCatCore.Services.Storage;
|
using AutoCatCore.Services.Storage;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
@ -65,7 +66,7 @@ public class AuthWindowViewModel: ViewModelBase
|
|||||||
(login, password) => login.Length > 3 && password.Length > 3);
|
(login, password) => login.Length > 3 && password.Length > 3);
|
||||||
|
|
||||||
LoginCommand = ReactiveCommand.CreateFromTask(Login, loginEnabled);
|
LoginCommand = ReactiveCommand.CreateFromTask(Login, loginEnabled);
|
||||||
LoginCommand.ThrownExceptions.Subscribe(ShowError);
|
LoginCommand.ThrownExceptions.Subscribe(Alerts.ShowError);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Login()
|
private async Task Login()
|
||||||
@ -74,16 +75,4 @@ public class AuthWindowViewModel: ViewModelBase
|
|||||||
await _storageService.SetUser(user);
|
await _storageService.SetUser(user);
|
||||||
ReplaceWithMainWindowEvent?.Invoke(this, EventArgs.Empty);
|
ReplaceWithMainWindowEvent?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void ShowError(Exception error)
|
|
||||||
{
|
|
||||||
var msgBox = MessageBoxManager.GetMessageBoxStandard(new MessageBoxStandardParams
|
|
||||||
{
|
|
||||||
ButtonDefinitions = ButtonEnum.Ok,
|
|
||||||
ContentTitle = "Error",
|
|
||||||
ContentMessage = error.Message
|
|
||||||
});
|
|
||||||
|
|
||||||
await msgBox.ShowAsync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
65
AutoCat/ViewModels/CheckNumberViewModel.cs
Normal file
65
AutoCat/ViewModels/CheckNumberViewModel.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reactive;
|
||||||
|
using System.Reactive.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using AutoCat.Utils;
|
||||||
|
using AutoCatCore.Model;
|
||||||
|
using AutoCatCore.Services.Api;
|
||||||
|
using DynamicData.Binding;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace AutoCat.ViewModels;
|
||||||
|
|
||||||
|
public class CheckNumberViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
#region Fields
|
||||||
|
|
||||||
|
private string _plateNumber = "";
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Dependencies
|
||||||
|
|
||||||
|
private readonly IApiService _apiService;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Commands
|
||||||
|
|
||||||
|
public ReactiveCommand<string, Unit> CheckCommand { get; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
public string PlateNumber
|
||||||
|
{
|
||||||
|
get => _plateNumber;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _plateNumber, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vehicle? Vehicle { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Events
|
||||||
|
|
||||||
|
public event EventHandler? AutoCloseEvent;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public CheckNumberViewModel(IApiService apiService)
|
||||||
|
{
|
||||||
|
_apiService = apiService;
|
||||||
|
|
||||||
|
var checkEnabled = this.WhenAnyValue(vm => vm.PlateNumber, n => n.Length >= 8);
|
||||||
|
CheckCommand = ReactiveCommand.CreateFromTask<string>(Check, checkEnabled);
|
||||||
|
CheckCommand.ThrownExceptions.Subscribe(Alerts.ShowError);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Check(string number)
|
||||||
|
{
|
||||||
|
Vehicle = await _apiService.CheckNumber(number);
|
||||||
|
AutoCloseEvent?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using AutoCatCore.Model;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Data;
|
using Avalonia.Data;
|
||||||
|
|||||||
38
AutoCat/Windows/CheckNumberDialog.axaml
Normal file
38
AutoCat/Windows/CheckNumberDialog.axaml
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:utils="using:AutoCat.Utils"
|
||||||
|
xmlns:vm="using:AutoCat.ViewModels"
|
||||||
|
xmlns:ext="using:AutoCat.Extensions"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="AutoCat.Windows.CheckNumberDialog"
|
||||||
|
x:DataType="vm:CheckNumberViewModel"
|
||||||
|
x:CompileBindings="true"
|
||||||
|
DataContext="{utils:ViewModelProvider vm:CheckNumberViewModel}">
|
||||||
|
|
||||||
|
<StackPanel Orientation="Vertical"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
Spacing="32"
|
||||||
|
Margin="0 16">
|
||||||
|
|
||||||
|
<Grid ColumnDefinitions="* 16 Auto" HorizontalAlignment="Stretch">
|
||||||
|
|
||||||
|
<TextBox Grid.Column="0"
|
||||||
|
Name="PlateNumberBox"
|
||||||
|
Watermark="Plate Number"
|
||||||
|
Text="{Binding PlateNumber}"
|
||||||
|
IsEnabled="{ReflectionBinding !CheckCommand.IsExecuting^}"/>
|
||||||
|
<Button Grid.Column="2"
|
||||||
|
Content="Check"
|
||||||
|
Command="{Binding CheckCommand}"
|
||||||
|
CommandParameter="{Binding #PlateNumberBox.Text}"
|
||||||
|
IsEnabled="{ReflectionBinding !CheckCommand.IsExecuting^}"/>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<ProgressBar IsIndeterminate="True"
|
||||||
|
IsVisible="{ReflectionBinding CheckCommand.IsExecuting^}"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
</UserControl>
|
||||||
15
AutoCat/Windows/CheckNumberDialog.axaml.cs
Normal file
15
AutoCat/Windows/CheckNumberDialog.axaml.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Controls.Primitives;
|
||||||
|
using Avalonia.Markup.Xaml;
|
||||||
|
using FluentAvalonia.UI.Controls;
|
||||||
|
|
||||||
|
namespace AutoCat.Windows;
|
||||||
|
|
||||||
|
public partial class CheckNumberDialog : UserControl
|
||||||
|
{
|
||||||
|
public CheckNumberDialog()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -27,7 +27,9 @@
|
|||||||
IsPaneOpen="false"
|
IsPaneOpen="false"
|
||||||
OpenPaneLength="180">
|
OpenPaneLength="180">
|
||||||
<ui:NavigationView.MenuItems>
|
<ui:NavigationView.MenuItems>
|
||||||
<ui:NavigationViewItem Content="History" Tag="HistoryPage" IconSource="Clock"/>
|
<ui:NavigationViewItem Content="New number" Tag="Check" IconSource="Add" SelectsOnInvoked="False"/>
|
||||||
|
<ui:NavigationViewItem Content="History" Tag="History" IconSource="Clock"/>
|
||||||
|
<ui:NavigationViewItem Content="Search" Tag="Search" IconSource="Find"/>
|
||||||
</ui:NavigationView.MenuItems>
|
</ui:NavigationView.MenuItems>
|
||||||
</ui:NavigationView>
|
</ui:NavigationView>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using AutoCat.Pages;
|
using AutoCat.Pages;
|
||||||
|
using AutoCat.ViewModels;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using FluentAvalonia.UI.Controls;
|
using FluentAvalonia.UI.Controls;
|
||||||
|
|
||||||
@ -16,7 +18,18 @@ public partial class MainWindow : Window
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
NavView.SelectionChanged += NavSelectionChanged;
|
NavView.SelectionChanged += NavSelectionChanged;
|
||||||
NavView.SelectedItem = NavView.MenuItems.First();
|
NavView.ItemInvoked += NavViewOnItemInvoked;
|
||||||
|
NavView.SelectedItem = NavView.MenuItems.First(x => (x as NavigationViewItem)?.Tag?.ToString() == "History");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NavViewOnItemInvoked(object? sender, NavigationViewItemInvokedEventArgs e)
|
||||||
|
{
|
||||||
|
switch (e.InvokedItemContainer.Tag)
|
||||||
|
{
|
||||||
|
case "Check":
|
||||||
|
ShowCheckNumberDialog();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NavSelectionChanged(object? sender, NavigationViewSelectionChangedEventArgs args)
|
private void NavSelectionChanged(object? sender, NavigationViewSelectionChangedEventArgs args)
|
||||||
@ -25,9 +38,41 @@ public partial class MainWindow : Window
|
|||||||
{
|
{
|
||||||
NavView.Content = _settingsPage;
|
NavView.Content = _settingsPage;
|
||||||
}
|
}
|
||||||
else
|
else if (args.SelectedItem is NavigationViewItem item)
|
||||||
{
|
{
|
||||||
|
switch (item.Tag)
|
||||||
|
{
|
||||||
|
case "History":
|
||||||
|
break;
|
||||||
|
case "Search":
|
||||||
NavView.Content = _historyPage;
|
NavView.Content = _historyPage;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void ShowCheckNumberDialog()
|
||||||
|
{
|
||||||
|
var dialog = new ContentDialog()
|
||||||
|
{
|
||||||
|
Title = "Check new number",
|
||||||
|
CloseButtonText = "Cancel"
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialogContent = new CheckNumberDialog();
|
||||||
|
dialog.Content = dialogContent;
|
||||||
|
|
||||||
|
var dialogTask = dialog.ShowAsync();
|
||||||
|
|
||||||
|
if (dialogContent.DataContext is CheckNumberViewModel vm)
|
||||||
|
{
|
||||||
|
vm.AutoCloseEvent += (sender, args) =>
|
||||||
|
{
|
||||||
|
dialog.Hide();
|
||||||
|
Console.WriteLine($"Checked number: {vm.Vehicle?.Number}");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
await dialogTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,7 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace AutoCat.Views;
|
namespace AutoCatCore.Model;
|
||||||
|
|
||||||
//[CreateFromString(MethodName = "AutoCat.Controls.PlateNumber.ConvertFromString")]
|
//[CreateFromString(MethodName = "AutoCat.Controls.PlateNumber.ConvertFromString")]
|
||||||
public class PlateNumber
|
public class PlateNumber
|
||||||
@ -37,9 +37,4 @@ public class PlateNumber
|
|||||||
{
|
{
|
||||||
return _numberEnglish[6..];
|
return _numberEnglish[6..];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PlateNumber ConvertFromString(string number)
|
|
||||||
{
|
|
||||||
return new PlateNumber(number);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -3,14 +3,21 @@ using System.Text.Json.Serialization;
|
|||||||
|
|
||||||
namespace AutoCatCore.Model
|
namespace AutoCatCore.Model
|
||||||
{
|
{
|
||||||
public class User
|
public class User(string email, string token)
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
public string Email { get; set; }
|
[MaxLength(50)]
|
||||||
public string? Token { get; set; }
|
public string Email { get; set; } = email;
|
||||||
|
|
||||||
|
[MaxLength(300)]
|
||||||
|
public string? Token { get; set; } = token;
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
|
[MaxLength(300)]
|
||||||
public string? FirebaseIdToken { get; set; }
|
public string? FirebaseIdToken { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
|
[MaxLength(300)]
|
||||||
public string? FirebaseRefreshToken { get; set; }
|
public string? FirebaseRefreshToken { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
using System.Net.Http.Json;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using AutoCat.Model.Requests;
|
using AutoCat.Model.Requests;
|
||||||
@ -14,13 +15,15 @@ public class ApiService : IApiService
|
|||||||
public ApiService(IStorageService storageService)
|
public ApiService(IStorageService storageService)
|
||||||
{
|
{
|
||||||
_httpClient = new HttpClient();
|
_httpClient = new HttpClient();
|
||||||
_httpClient.BaseAddress = new Uri("https://vps.aliencat.pro:8443");
|
_httpClient.BaseAddress = new Uri("http://127.0.0.1:3000");
|
||||||
SetAccessToken(storageService.AuthToken);
|
SetAccessToken(storageService.AuthToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static T GetDataOrThrow<T>(string response)
|
private static async Task<T> GetDataOrThrow<T>(HttpResponseMessage response)
|
||||||
{
|
{
|
||||||
var resp = JsonSerializer.Deserialize<Response<T>>(response, new JsonSerializerOptions {
|
string responseStr = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
var resp = JsonSerializer.Deserialize<Response<T>>(responseStr, new JsonSerializerOptions {
|
||||||
PropertyNameCaseInsensitive = true
|
PropertyNameCaseInsensitive = true
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -50,8 +53,7 @@ public class ApiService : IApiService
|
|||||||
});
|
});
|
||||||
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||||
var response = await _httpClient.PostAsync("user/login", content);
|
var response = await _httpClient.PostAsync("user/login", content);
|
||||||
var respStr = await response.Content.ReadAsStringAsync();
|
var result = await GetDataOrThrow<User>(response);
|
||||||
var result = GetDataOrThrow<User>(respStr);
|
|
||||||
SetAccessToken(result.Token);
|
SetAccessToken(result.Token);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -59,7 +61,12 @@ public class ApiService : IApiService
|
|||||||
public async Task<PagedResponse<Vehicle>> GetVehicles()
|
public async Task<PagedResponse<Vehicle>> GetVehicles()
|
||||||
{
|
{
|
||||||
var response = await _httpClient.GetAsync("vehicles");
|
var response = await _httpClient.GetAsync("vehicles");
|
||||||
var respStr = await response.Content.ReadAsStringAsync();
|
return await GetDataOrThrow<PagedResponse<Vehicle>>(response);
|
||||||
return GetDataOrThrow<PagedResponse<Vehicle>>(respStr);
|
}
|
||||||
|
|
||||||
|
public async Task<Vehicle> CheckNumber(string number)
|
||||||
|
{
|
||||||
|
var response = await _httpClient.PostAsJsonAsync("vehicles/check", new { number });
|
||||||
|
return await GetDataOrThrow<Vehicle>(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7,4 +7,5 @@ public interface IApiService
|
|||||||
{
|
{
|
||||||
Task<User> Login(string email, string password);
|
Task<User> Login(string email, string password);
|
||||||
Task<PagedResponse<Vehicle>> GetVehicles();
|
Task<PagedResponse<Vehicle>> GetVehicles();
|
||||||
|
Task<Vehicle> CheckNumber(string number);
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user