diff --git a/AutoService.sln b/AutoService.sln
new file mode 100644
index 0000000..44ce420
--- /dev/null
+++ b/AutoService.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.14.36623.8 d17.14
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoService", "AutoService\AutoService.csproj", "{5845584C-1904-4184-B773-BCE9FE08B4CA}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {5845584C-1904-4184-B773-BCE9FE08B4CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5845584C-1904-4184-B773-BCE9FE08B4CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5845584C-1904-4184-B773-BCE9FE08B4CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5845584C-1904-4184-B773-BCE9FE08B4CA}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {7DAD94C8-56AB-4CA7-B7DE-8C85BB9DA95F}
+ EndGlobalSection
+EndGlobal
diff --git a/AutoService/App.axaml b/AutoService/App.axaml
new file mode 100644
index 0000000..85f1f93
--- /dev/null
+++ b/AutoService/App.axaml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AutoService/App.axaml.cs b/AutoService/App.axaml.cs
new file mode 100644
index 0000000..e96aa66
--- /dev/null
+++ b/AutoService/App.axaml.cs
@@ -0,0 +1,55 @@
+using AutoService.ViewModels;
+using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Data.Core.Plugins;
+using Avalonia.Markup.Xaml;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Linq;
+
+namespace AutoService
+{
+ public partial class App : Application
+ {
+ private readonly IServiceProvider _provider;
+
+ public App(IServiceProvider provider)
+ {
+ _provider = provider;
+ }
+ public override void Initialize()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+
+ public override void OnFrameworkInitializationCompleted()
+ {
+ if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+ {
+ // Avoid duplicate validations from both Avalonia and the CommunityToolkit.
+ // More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins
+ DisableAvaloniaDataAnnotationValidation();
+
+ var win = _provider.GetRequiredService();
+ var vm = _provider.GetRequiredService();
+ win.DataContext = vm;
+ desktop.MainWindow = win;
+ }
+
+ base.OnFrameworkInitializationCompleted();
+ }
+
+ private void DisableAvaloniaDataAnnotationValidation()
+ {
+ // Get an array of plugins to remove
+ var dataValidationPluginsToRemove =
+ BindingPlugins.DataValidators.OfType().ToArray();
+
+ // remove each entry found
+ foreach (var plugin in dataValidationPluginsToRemove)
+ {
+ BindingPlugins.DataValidators.Remove(plugin);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/AutoService/AutoService.csproj b/AutoService/AutoService.csproj
new file mode 100644
index 0000000..6b8f581
--- /dev/null
+++ b/AutoService/AutoService.csproj
@@ -0,0 +1,35 @@
+
+
+ WinExe
+ net8.0
+ enable
+ app.manifest
+ true
+
+
+
+
+
+
+
+
+
+
+ None
+ All
+
+
+
+
+
+
+
+
+
+ ReceiptWindow.axaml
+
+
+ WorksWindow.axaml
+
+
+
diff --git a/AutoService/Models/BaseRepository.cs b/AutoService/Models/BaseRepository.cs
new file mode 100644
index 0000000..4ce9065
--- /dev/null
+++ b/AutoService/Models/BaseRepository.cs
@@ -0,0 +1,52 @@
+using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Options;
+using MySqlConnector;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AutoService.Models
+{
+ public class BaseRepository
+ {
+ public readonly DatabaseSettings _databaseSetting;
+
+ protected MySqlConnection connection;
+
+ public BaseRepository(IOptions databaseSettings)
+ {
+ _databaseSetting = databaseSettings.Value;
+ connection = new MySqlConnection(_databaseSetting.ConnectionString);
+
+ }
+ public bool OpenConnection()
+ {
+ try
+ {
+ connection.Open();
+ return true;
+ }catch(Exception e)
+ {
+ Console.WriteLine(e);
+ return false;
+ }
+ }
+
+ public bool CloseConnection()
+ {
+ try
+ {
+ connection.Close();
+ return true;
+ }
+ catch(Exception e)
+ {
+ Console.WriteLine(e);
+ return false;
+ }
+ }
+
+ }
+}
diff --git a/AutoService/Models/DatabaseSettings.cs b/AutoService/Models/DatabaseSettings.cs
new file mode 100644
index 0000000..ccc5fd3
--- /dev/null
+++ b/AutoService/Models/DatabaseSettings.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AutoService.Models
+{
+ public class DatabaseSettings
+ {
+ public string ConnectionString { get; set; }
+ }
+}
diff --git a/AutoService/Models/IServiceRepository.cs b/AutoService/Models/IServiceRepository.cs
new file mode 100644
index 0000000..9b8afe4
--- /dev/null
+++ b/AutoService/Models/IServiceRepository.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AutoService.Models
+{
+ public interface IServiceRepository
+ {
+ IEnumerable GetAll();
+ }
+}
diff --git a/AutoService/Models/IWorkRepository.cs b/AutoService/Models/IWorkRepository.cs
new file mode 100644
index 0000000..f0f55e7
--- /dev/null
+++ b/AutoService/Models/IWorkRepository.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AutoService.Models
+{
+ public interface IWorkRepository
+ {
+ IEnumerable GetByServiceId(int serviceId);
+
+ }
+}
diff --git a/AutoService/Models/LocalContainer.cs b/AutoService/Models/LocalContainer.cs
new file mode 100644
index 0000000..95a3ebb
--- /dev/null
+++ b/AutoService/Models/LocalContainer.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AutoService.Models
+{
+ public class LocalContainer
+ {
+ public Dictionary StringValues { get; set; } = new();
+
+ public Service SelectedService { get; set; }
+
+ public ObservableCollection Works { get; set; }
+
+ }
+}
diff --git a/AutoService/Models/Service.cs b/AutoService/Models/Service.cs
new file mode 100644
index 0000000..159efca
--- /dev/null
+++ b/AutoService/Models/Service.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AutoService.Models
+{
+ public class Service
+ {
+ public int Id { get; set; }
+ public string Title { get; set; }
+ public string Description { get; set; }
+ }
+}
diff --git a/AutoService/Models/ServiceRepository.cs b/AutoService/Models/ServiceRepository.cs
new file mode 100644
index 0000000..d77bedb
--- /dev/null
+++ b/AutoService/Models/ServiceRepository.cs
@@ -0,0 +1,46 @@
+using Microsoft.Extensions.Options;
+using MySqlConnector;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AutoService.Models
+{
+ public class ServiceRepository : BaseRepository, IServiceRepository
+ {
+ public ServiceRepository(IOptions databaseSettings) : base(databaseSettings)
+ {
+ }
+
+ public IEnumerable GetAll()
+ {
+ string sql = "SELECT * FROM services";
+ List result = new();
+
+ try
+ {
+ OpenConnection();
+ using var mc = new MySqlCommand(sql, connection);
+ using var reader = mc.ExecuteReader();
+ while (reader.Read())
+ {
+ result.Add(new Service()
+ {
+ Id = reader.GetInt32("id"),
+ Title = reader.GetString("title"),
+ Description = reader.GetString("description")
+ });
+ }
+ CloseConnection();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ }
+ return result;
+
+ }
+ }
+}
diff --git a/AutoService/Models/Work.cs b/AutoService/Models/Work.cs
new file mode 100644
index 0000000..2fdff5f
--- /dev/null
+++ b/AutoService/Models/Work.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AutoService.Models
+{
+ public class Work
+ {
+ public string Title { get; set; }
+ public int Price { get; set; }
+
+ }
+}
diff --git a/AutoService/Models/WorkIsChecked.cs b/AutoService/Models/WorkIsChecked.cs
new file mode 100644
index 0000000..7e33c3b
--- /dev/null
+++ b/AutoService/Models/WorkIsChecked.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AutoService.Models
+{
+ public class WorkIsChecked
+ {
+ public bool IsChecked { get; set; }
+ public Work Work { get; set; }
+ }
+}
diff --git a/AutoService/Models/WorkRepository.cs b/AutoService/Models/WorkRepository.cs
new file mode 100644
index 0000000..41365a2
--- /dev/null
+++ b/AutoService/Models/WorkRepository.cs
@@ -0,0 +1,45 @@
+using Microsoft.Extensions.Options;
+using MySqlConnector;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AutoService.Models
+{
+ public class WorkRepository : BaseRepository, IWorkRepository
+ {
+ public WorkRepository(IOptions databaseSettings) : base(databaseSettings)
+ {
+ }
+
+ public IEnumerable GetByServiceId(int serviceId)
+ {
+ string sql = "SELECT work_name, price FROM works WHERE service_id=@SID";
+ List result = new();
+ try
+ {
+ OpenConnection();
+ using var mc = new MySqlCommand(sql, connection);
+ mc.Parameters.AddWithValue("@SID", serviceId);
+ using var reader = mc.ExecuteReader();
+ while (reader.Read())
+ {
+ result.Add(new Work()
+ {
+ Title = reader.GetString("work_name"),
+ Price = reader.GetInt32("price")
+
+ });
+ }
+ CloseConnection();
+
+ }catch(Exception e)
+ {
+ Console.WriteLine(e);
+ }
+ return result;
+ }
+ }
+}
diff --git a/AutoService/Program.cs b/AutoService/Program.cs
new file mode 100644
index 0000000..9f2e95a
--- /dev/null
+++ b/AutoService/Program.cs
@@ -0,0 +1,50 @@
+using AutoService.Models;
+using AutoService.ViewModels;
+using Avalonia;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using System;
+
+namespace AutoService
+{
+ internal class Program
+ {
+ // Initialization code. Don't use any Avalonia, third-party APIs or any
+ // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
+ // yet and stuff might break.
+ [STAThread]
+ public static void Main(string[] args)
+ {
+
+ var host = Host.CreateDefaultBuilder()
+ .ConfigureAppConfiguration((hostingContext, config) =>
+ {
+ config.SetBasePath(AppContext.BaseDirectory).AddJsonFile("appsettings.json").AddEnvironmentVariables();
+ })
+ .ConfigureServices((c,s) =>
+ {
+ s.Configure(c.Configuration.GetSection("DatabaseSettings"));
+ s.AddTransient();
+ s.AddTransient();
+ s.AddTransient();
+ s.AddTransient();
+ s.AddTransient();
+ s.AddTransient();
+ s.AddSingleton();
+ s.AddSingleton();
+ s.AddSingleton();
+
+
+ }).Build();
+ BuildAvaloniaApp(host.Services)
+ .StartWithClassicDesktopLifetime(args);
+ }
+ // Avalonia configuration, don't remove; also used by visual designer.
+ public static AppBuilder BuildAvaloniaApp(IServiceProvider provider)
+ => AppBuilder.Configure(() => new App(provider))
+ .UsePlatformDetect()
+ .WithInterFont()
+ .LogToTrace();
+ }
+}
diff --git a/AutoService/ViewModels/MainWindowVM.cs b/AutoService/ViewModels/MainWindowVM.cs
new file mode 100644
index 0000000..e87b084
--- /dev/null
+++ b/AutoService/ViewModels/MainWindowVM.cs
@@ -0,0 +1,89 @@
+using AutoService.Models;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using Microsoft.Extensions.DependencyInjection;
+using MsBox.Avalonia;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AutoService.ViewModels
+{
+ public partial class MainWindowVM:ViewModelBase
+ {
+ private readonly IServiceProvider _serviceProvider;
+ private readonly IServiceRepository _serviceRepository;
+ private readonly LocalContainer _container;
+
+ [ObservableProperty]
+ private ObservableCollection services;
+
+ [ObservableProperty]
+ private string clientName;
+
+ [ObservableProperty]
+ private string autoModel;
+
+ [ObservableProperty]
+ private Service selectedService;
+
+
+ public MainWindowVM(IServiceProvider serviceProvider, IServiceRepository serviceRepository, LocalContainer localContainer)
+ {
+ _serviceProvider = serviceProvider;
+ _serviceRepository = serviceRepository;
+ _container = localContainer;
+ ClientName = "";
+ AutoModel = "";
+ try
+ {
+ services = new ObservableCollection(_serviceRepository.GetAll());
+ SelectedService = Services.First();
+ }
+ catch(Exception e)
+ {
+ Console.WriteLine(e);
+ services = new();
+ }
+
+ }
+
+ [RelayCommand]
+ public async Task StartWorksWindowAsync()
+ {
+ if (ClientName.Length > 2 && AutoModel.Length > 2)
+ {
+ if (!_container.StringValues.ContainsKey("ClientName"))
+ {
+ _container.StringValues.Add("ClientName", ClientName);
+ }
+ else
+ {
+ _container.StringValues["ClientName"] = ClientName;
+ }
+ if (!_container.StringValues.ContainsKey("AutoModel"))
+ {
+ _container.StringValues.Add("AutoModel", AutoModel);
+ }
+ else
+ {
+ _container.StringValues["AutoModel"] = AutoModel;
+ }
+
+ var vm = _serviceProvider.GetRequiredService();
+ var win = _serviceProvider.GetRequiredService();
+ win.DataContext = vm;
+ win.Show();
+ }
+ else
+ {
+ var errWin = MessageBoxManager.GetMessageBoxStandard("Косяк!", "Поля \"Имя\" и \"Марка машины\" должны быть заполнены!", MsBox.Avalonia.Enums.ButtonEnum.Ok);
+ await errWin.ShowAsync();
+ }
+ }
+
+ }
+}
diff --git a/AutoService/ViewModels/ReceiptWindowVM.cs b/AutoService/ViewModels/ReceiptWindowVM.cs
new file mode 100644
index 0000000..18c8c25
--- /dev/null
+++ b/AutoService/ViewModels/ReceiptWindowVM.cs
@@ -0,0 +1,47 @@
+using AutoService.Models;
+using CommunityToolkit.Mvvm.ComponentModel;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AutoService.ViewModels
+{
+ public partial class ReceiptWindowVM: ViewModelBase
+ {
+
+ private readonly IServiceProvider _serviceProvider;
+
+ private readonly LocalContainer _localContainer;
+
+
+ [ObservableProperty]
+ private ObservableCollection works;
+
+ [ObservableProperty]
+ private int sumPrice = 0;
+
+ private double discount = 0;
+
+ [ObservableProperty]
+ private string discountText;
+
+ [ObservableProperty]
+ private double totalPrice;
+ public ReceiptWindowVM(IServiceProvider serviceProvider, ObservableCollection works, LocalContainer localContainer)
+ {
+ _serviceProvider = serviceProvider;
+ _localContainer = localContainer;
+ Works = works;
+ foreach (var item in Works) sumPrice += item.Price;
+ if (sumPrice >= 10_000) discount = 0.1;
+ else if (sumPrice >= 5_000) discount = 0.05;
+ DiscountText = (discount * 100).ToString() + "%";
+
+ TotalPrice = sumPrice * (1-discount);
+
+ }
+ }
+}
diff --git a/AutoService/ViewModels/ViewModelBase.cs b/AutoService/ViewModels/ViewModelBase.cs
new file mode 100644
index 0000000..bb53212
--- /dev/null
+++ b/AutoService/ViewModels/ViewModelBase.cs
@@ -0,0 +1,13 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AutoService.ViewModels
+{
+ public class ViewModelBase: ObservableObject
+ {
+ }
+}
diff --git a/AutoService/ViewModels/WorksWindowVM.cs b/AutoService/ViewModels/WorksWindowVM.cs
new file mode 100644
index 0000000..04dabdf
--- /dev/null
+++ b/AutoService/ViewModels/WorksWindowVM.cs
@@ -0,0 +1,57 @@
+using AutoService.Models;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AutoService.ViewModels
+{
+ public partial class WorksWindowVM:ViewModelBase
+ {
+ private readonly IServiceProvider _serviceProvider;
+ private readonly LocalContainer _localContainer;
+
+ private Service _service;
+
+ [ObservableProperty]
+ private ObservableCollection works;
+
+
+ public WorksWindowVM(IServiceProvider serviceProvider, IWorkRepository workRepository, LocalContainer container)
+ {
+ _serviceProvider = serviceProvider;
+ _service = container.SelectedService;
+ _localContainer = container;
+ Works = new ObservableCollection();
+ foreach(Work work in workRepository.GetByServiceId(_service.Id))
+ {
+ Works.Add(new WorkIsChecked
+ {
+ Work = work,
+ IsChecked = false
+ });
+ }
+
+ }
+
+ [RelayCommand]
+ public void CalculateCount()
+ {
+ ObservableCollection selectedWorks = new();
+ foreach(var work in Works)
+ {
+ if (work.IsChecked) selectedWorks.Add(work.Work);
+ }
+ var vm = ActivatorUtilities.CreateInstance(_serviceProvider, selectedWorks, _localContainer);
+ var win = _serviceProvider.GetRequiredService();
+ win.DataContext = vm;
+ win.Show();
+ }
+
+ }
+}
diff --git a/AutoService/Views/MainWindow.axaml b/AutoService/Views/MainWindow.axaml
new file mode 100644
index 0000000..03db5d8
--- /dev/null
+++ b/AutoService/Views/MainWindow.axaml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AutoService/Views/MainWindow.axaml.cs b/AutoService/Views/MainWindow.axaml.cs
new file mode 100644
index 0000000..eb01408
--- /dev/null
+++ b/AutoService/Views/MainWindow.axaml.cs
@@ -0,0 +1,12 @@
+using Avalonia.Controls;
+
+namespace AutoService
+{
+ public partial class MainWindow : Window
+ {
+ public MainWindow()
+ {
+ InitializeComponent();
+ }
+ }
+}
\ No newline at end of file
diff --git a/AutoService/Views/ReceiptWindow.axaml b/AutoService/Views/ReceiptWindow.axaml
new file mode 100644
index 0000000..3e69a88
--- /dev/null
+++ b/AutoService/Views/ReceiptWindow.axaml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AutoService/Views/ReceiptWindow.axaml.cs b/AutoService/Views/ReceiptWindow.axaml.cs
new file mode 100644
index 0000000..0305c08
--- /dev/null
+++ b/AutoService/Views/ReceiptWindow.axaml.cs
@@ -0,0 +1,12 @@
+using Avalonia.Controls;
+
+namespace AutoService
+{
+ public partial class ReceiptWindow : Window
+ {
+ public ReceiptWindow()
+ {
+ InitializeComponent();
+ }
+ }
+}
\ No newline at end of file
diff --git a/AutoService/Views/WorksWindow.axaml b/AutoService/Views/WorksWindow.axaml
new file mode 100644
index 0000000..c6fed33
--- /dev/null
+++ b/AutoService/Views/WorksWindow.axaml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AutoService/Views/WorksWindow.axaml.cs b/AutoService/Views/WorksWindow.axaml.cs
new file mode 100644
index 0000000..da2b00e
--- /dev/null
+++ b/AutoService/Views/WorksWindow.axaml.cs
@@ -0,0 +1,13 @@
+using AutoService.ViewModels;
+using Avalonia.Controls;
+
+namespace AutoService
+{
+ public partial class WorksWindow : Window
+ {
+ public WorksWindow()
+ {
+ InitializeComponent();
+ }
+ }
+}
\ No newline at end of file
diff --git a/AutoService/app.manifest b/AutoService/app.manifest
new file mode 100644
index 0000000..95560e2
--- /dev/null
+++ b/AutoService/app.manifest
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AutoService/appsetting.json b/AutoService/appsetting.json
new file mode 100644
index 0000000..92cd1b7
--- /dev/null
+++ b/AutoService/appsetting.json
@@ -0,0 +1,5 @@
+{
+ "DatabaseSettings": {
+ "ConnectionString": "server=192.168.200.13;user=student;password=student;database=auto_service_db"
+ }
+}
\ No newline at end of file