diff --git a/ServiceApp.sln b/ServiceApp.sln
new file mode 100644
index 0000000..9ba1be3
--- /dev/null
+++ b/ServiceApp.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.11.35222.181
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceApp", "ServiceApp\ServiceApp.csproj", "{F2BD7127-5A3B-4AF1-89E4-C60B70EB2E6B}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F2BD7127-5A3B-4AF1-89E4-C60B70EB2E6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F2BD7127-5A3B-4AF1-89E4-C60B70EB2E6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F2BD7127-5A3B-4AF1-89E4-C60B70EB2E6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F2BD7127-5A3B-4AF1-89E4-C60B70EB2E6B}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {A812EF99-15E4-4DD1-A3AD-370E1AB49A94}
+ EndGlobalSection
+EndGlobal
diff --git a/ServiceApp/App.axaml b/ServiceApp/App.axaml
new file mode 100644
index 0000000..1d5b7f7
--- /dev/null
+++ b/ServiceApp/App.axaml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ServiceApp/App.axaml.cs b/ServiceApp/App.axaml.cs
new file mode 100644
index 0000000..1c6f03f
--- /dev/null
+++ b/ServiceApp/App.axaml.cs
@@ -0,0 +1,24 @@
+using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Markup.Xaml;
+
+namespace ServiceApp
+{
+ public partial class App : Application
+ {
+ public override void Initialize()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+
+ public override void OnFrameworkInitializationCompleted()
+ {
+ if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+ {
+ desktop.MainWindow = new MainWindow();
+ }
+
+ base.OnFrameworkInitializationCompleted();
+ }
+ }
+}
\ No newline at end of file
diff --git a/ServiceApp/Assets/diz.jpg b/ServiceApp/Assets/diz.jpg
new file mode 100644
index 0000000..bb6d0c6
Binary files /dev/null and b/ServiceApp/Assets/diz.jpg differ
diff --git a/ServiceApp/Assets/download.png b/ServiceApp/Assets/download.png
new file mode 100644
index 0000000..decc481
Binary files /dev/null and b/ServiceApp/Assets/download.png differ
diff --git a/ServiceApp/Assets/rulevoe-upravlenie-avtomobilya.jpg b/ServiceApp/Assets/rulevoe-upravlenie-avtomobilya.jpg
new file mode 100644
index 0000000..1f63a94
Binary files /dev/null and b/ServiceApp/Assets/rulevoe-upravlenie-avtomobilya.jpg differ
diff --git a/ServiceApp/Assets/transmission.jpg b/ServiceApp/Assets/transmission.jpg
new file mode 100644
index 0000000..d6bee7a
Binary files /dev/null and b/ServiceApp/Assets/transmission.jpg differ
diff --git a/ServiceApp/Assets/АКПП.jpg b/ServiceApp/Assets/АКПП.jpg
new file mode 100644
index 0000000..05712af
Binary files /dev/null and b/ServiceApp/Assets/АКПП.jpg differ
diff --git a/ServiceApp/Assets/Вариатор.jpg b/ServiceApp/Assets/Вариатор.jpg
new file mode 100644
index 0000000..dab9ab0
Binary files /dev/null and b/ServiceApp/Assets/Вариатор.jpg differ
diff --git a/ServiceApp/Assets/Выхлопная система.jpg b/ServiceApp/Assets/Выхлопная система.jpg
new file mode 100644
index 0000000..84a5499
Binary files /dev/null and b/ServiceApp/Assets/Выхлопная система.jpg differ
diff --git a/ServiceApp/Assets/ГУР.png b/ServiceApp/Assets/ГУР.png
new file mode 100644
index 0000000..f44d643
Binary files /dev/null and b/ServiceApp/Assets/ГУР.png differ
diff --git a/ServiceApp/Assets/Двигатель.png b/ServiceApp/Assets/Двигатель.png
new file mode 100644
index 0000000..9887cf5
Binary files /dev/null and b/ServiceApp/Assets/Двигатель.png differ
diff --git a/ServiceApp/Assets/Дополнительные услуги.png b/ServiceApp/Assets/Дополнительные услуги.png
new file mode 100644
index 0000000..fea97ed
Binary files /dev/null and b/ServiceApp/Assets/Дополнительные услуги.png differ
diff --git a/ServiceApp/Assets/КПП.png b/ServiceApp/Assets/КПП.png
new file mode 100644
index 0000000..f480034
Binary files /dev/null and b/ServiceApp/Assets/КПП.png differ
diff --git a/ServiceApp/Assets/Кондиционер.jpg b/ServiceApp/Assets/Кондиционер.jpg
new file mode 100644
index 0000000..7f18699
Binary files /dev/null and b/ServiceApp/Assets/Кондиционер.jpg differ
diff --git a/ServiceApp/Assets/Подвеска.png b/ServiceApp/Assets/Подвеска.png
new file mode 100644
index 0000000..0b310b2
Binary files /dev/null and b/ServiceApp/Assets/Подвеска.png differ
diff --git a/ServiceApp/Assets/Сцепление.jpg b/ServiceApp/Assets/Сцепление.jpg
new file mode 100644
index 0000000..dea13cb
Binary files /dev/null and b/ServiceApp/Assets/Сцепление.jpg differ
diff --git a/ServiceApp/Assets/Техническое обслуживание.png b/ServiceApp/Assets/Техническое обслуживание.png
new file mode 100644
index 0000000..b9c2d04
Binary files /dev/null and b/ServiceApp/Assets/Техническое обслуживание.png differ
diff --git a/ServiceApp/Assets/Топливная система.png b/ServiceApp/Assets/Топливная система.png
new file mode 100644
index 0000000..7990d1e
Binary files /dev/null and b/ServiceApp/Assets/Топливная система.png differ
diff --git a/ServiceApp/Assets/Шиномонтаж.jpg b/ServiceApp/Assets/Шиномонтаж.jpg
new file mode 100644
index 0000000..b17156e
Binary files /dev/null and b/ServiceApp/Assets/Шиномонтаж.jpg differ
diff --git a/ServiceApp/Assets/Электрика.png b/ServiceApp/Assets/Электрика.png
new file mode 100644
index 0000000..ac0bd50
Binary files /dev/null and b/ServiceApp/Assets/Электрика.png differ
diff --git a/ServiceApp/EntityModels/Client.cs b/ServiceApp/EntityModels/Client.cs
new file mode 100644
index 0000000..d7ae129
--- /dev/null
+++ b/ServiceApp/EntityModels/Client.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+
+namespace ServiceApp.EnityModels;
+
+public partial class Client
+{
+ public int Id { get; set; }
+
+ public string Firstname { get; set; } = null!;
+
+ public string Lastname { get; set; } = null!;
+
+ public string? Patronymic { get; set; }
+
+ public DateOnly? Birthday { get; set; }
+
+ public DateTime Registrationdate { get; set; }
+
+ public string? Email { get; set; }
+
+ public string Phone { get; set; } = null!;
+
+ public int Gendercode { get; set; }
+
+ public string? Photopath { get; set; }
+
+ public virtual ICollection Clientservices { get; set; } = new List();
+
+ public virtual Gender GendercodeNavigation { get; set; } = null!;
+
+ public virtual ICollection Tags { get; set; } = new List();
+}
diff --git a/ServiceApp/EntityModels/Clientservice.cs b/ServiceApp/EntityModels/Clientservice.cs
new file mode 100644
index 0000000..1f1c6c7
--- /dev/null
+++ b/ServiceApp/EntityModels/Clientservice.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+
+namespace ServiceApp.EnityModels;
+
+public partial class Clientservice
+{
+ public int Id { get; set; }
+
+ public int Clientid { get; set; }
+
+ public int Serviceid { get; set; }
+
+ public DateTime Starttime { get; set; }
+
+ public string? Comment { get; set; }
+
+ public virtual Client Client { get; set; } = null!;
+
+ public virtual ICollection Documentbyservices { get; set; } = new List();
+
+ public virtual ICollection Productsales { get; set; } = new List();
+
+ public virtual Service Service { get; set; } = null!;
+}
diff --git a/ServiceApp/EntityModels/Documentbyservice.cs b/ServiceApp/EntityModels/Documentbyservice.cs
new file mode 100644
index 0000000..85859d7
--- /dev/null
+++ b/ServiceApp/EntityModels/Documentbyservice.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+
+namespace ServiceApp.EnityModels;
+
+public partial class Documentbyservice
+{
+ public int Id { get; set; }
+
+ public int Clientserviceid { get; set; }
+
+ public string Documentpath { get; set; } = null!;
+
+ public virtual Clientservice Clientservice { get; set; } = null!;
+}
diff --git a/ServiceApp/EntityModels/Gender.cs b/ServiceApp/EntityModels/Gender.cs
new file mode 100644
index 0000000..027d456
--- /dev/null
+++ b/ServiceApp/EntityModels/Gender.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+
+namespace ServiceApp.EnityModels;
+
+public partial class Gender
+{
+ public int Code { get; set; }
+
+ public string? Name { get; set; }
+
+ public virtual ICollection Clients { get; set; } = new List();
+}
diff --git a/ServiceApp/EntityModels/IsajkinContext.cs b/ServiceApp/EntityModels/IsajkinContext.cs
new file mode 100644
index 0000000..84a51bc
--- /dev/null
+++ b/ServiceApp/EntityModels/IsajkinContext.cs
@@ -0,0 +1,334 @@
+using System;
+using System.Collections.Generic;
+using Microsoft.EntityFrameworkCore;
+
+namespace ServiceApp.EnityModels;
+
+public partial class IsajkinContext : DbContext
+{
+ public IsajkinContext()
+ {
+ }
+
+ public IsajkinContext(DbContextOptions options)
+ : base(options)
+ {
+ }
+
+ public virtual DbSet Clients { get; set; }
+
+ public virtual DbSet Clientservices { get; set; }
+
+ public virtual DbSet Documentbyservices { get; set; }
+
+ public virtual DbSet Genders { get; set; }
+
+ public virtual DbSet Manufacturers { get; set; }
+
+ public virtual DbSet Products { get; set; }
+
+ public virtual DbSet Productphotos { get; set; }
+
+ public virtual DbSet Productsales { get; set; }
+
+ public virtual DbSet Services { get; set; }
+
+ public virtual DbSet Servicephotos { get; set; }
+
+ public virtual DbSet Tags { get; set; }
+
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
+ => optionsBuilder.UseNpgsql("Host=45.67.56.214;Port=5454;Username=isajkin;Password=hqD9f9EZ");
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ modelBuilder.Entity(entity =>
+ {
+ entity.HasKey(e => e.Id).HasName("client_pkey");
+
+ entity.ToTable("client");
+
+ entity.Property(e => e.Id).HasColumnName("id");
+ entity.Property(e => e.Birthday).HasColumnName("birthday");
+ entity.Property(e => e.Email)
+ .HasMaxLength(255)
+ .HasColumnName("email");
+ entity.Property(e => e.Firstname)
+ .HasMaxLength(50)
+ .HasColumnName("firstname");
+ entity.Property(e => e.Gendercode).HasColumnName("gendercode");
+ entity.Property(e => e.Lastname)
+ .HasMaxLength(50)
+ .HasColumnName("lastname");
+ entity.Property(e => e.Patronymic)
+ .HasMaxLength(50)
+ .HasColumnName("patronymic");
+ entity.Property(e => e.Phone)
+ .HasMaxLength(20)
+ .HasColumnName("phone");
+ entity.Property(e => e.Photopath)
+ .HasMaxLength(1000)
+ .HasColumnName("photopath");
+ entity.Property(e => e.Registrationdate)
+ .HasColumnType("timestamp(6) without time zone")
+ .HasColumnName("registrationdate");
+
+ entity.HasOne(d => d.GendercodeNavigation).WithMany(p => p.Clients)
+ .HasForeignKey(d => d.Gendercode)
+ .OnDelete(DeleteBehavior.ClientSetNull)
+ .HasConstraintName("fk_client_gender");
+
+ entity.HasMany(d => d.Tags).WithMany(p => p.Clients)
+ .UsingEntity>(
+ "Tagofclient",
+ r => r.HasOne().WithMany()
+ .HasForeignKey("Tagid")
+ .OnDelete(DeleteBehavior.ClientSetNull)
+ .HasConstraintName("fk_tagofclient_tag"),
+ l => l.HasOne().WithMany()
+ .HasForeignKey("Clientid")
+ .OnDelete(DeleteBehavior.ClientSetNull)
+ .HasConstraintName("fk_tagofclient_client"),
+ j =>
+ {
+ j.HasKey("Clientid", "Tagid").HasName("tagofclient_pkey");
+ j.ToTable("tagofclient");
+ j.IndexerProperty("Clientid").HasColumnName("clientid");
+ j.IndexerProperty("Tagid").HasColumnName("tagid");
+ });
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.HasKey(e => e.Id).HasName("clientservice_pkey");
+
+ entity.ToTable("clientservice");
+
+ entity.Property(e => e.Id).HasColumnName("id");
+ entity.Property(e => e.Clientid).HasColumnName("clientid");
+ entity.Property(e => e.Comment).HasColumnName("comment");
+ entity.Property(e => e.Serviceid).HasColumnName("serviceid");
+ entity.Property(e => e.Starttime)
+ .HasColumnType("timestamp(6) without time zone")
+ .HasColumnName("starttime");
+
+ entity.HasOne(d => d.Client).WithMany(p => p.Clientservices)
+ .HasForeignKey(d => d.Clientid)
+ .OnDelete(DeleteBehavior.ClientSetNull)
+ .HasConstraintName("fk_clientservice_client");
+
+ entity.HasOne(d => d.Service).WithMany(p => p.Clientservices)
+ .HasForeignKey(d => d.Serviceid)
+ .OnDelete(DeleteBehavior.ClientSetNull)
+ .HasConstraintName("fk_clientservice_service");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.HasKey(e => e.Id).HasName("documentbyservice_pkey");
+
+ entity.ToTable("documentbyservice");
+
+ entity.Property(e => e.Id).HasColumnName("id");
+ entity.Property(e => e.Clientserviceid).HasColumnName("clientserviceid");
+ entity.Property(e => e.Documentpath)
+ .HasMaxLength(1000)
+ .HasColumnName("documentpath");
+
+ entity.HasOne(d => d.Clientservice).WithMany(p => p.Documentbyservices)
+ .HasForeignKey(d => d.Clientserviceid)
+ .OnDelete(DeleteBehavior.ClientSetNull)
+ .HasConstraintName("fk_documentbyservice_clientservice");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.HasKey(e => e.Code).HasName("gender_pkey");
+
+ entity.ToTable("gender");
+
+ entity.Property(e => e.Code).HasColumnName("code");
+ entity.Property(e => e.Name)
+ .HasMaxLength(10)
+ .HasColumnName("name");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.HasKey(e => e.Id).HasName("manufacturer_pkey");
+
+ entity.ToTable("manufacturer");
+
+ entity.Property(e => e.Id).HasColumnName("id");
+ entity.Property(e => e.Name)
+ .HasMaxLength(100)
+ .HasColumnName("name");
+ entity.Property(e => e.Startdate).HasColumnName("startdate");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.HasKey(e => e.Id).HasName("product_pkey");
+
+ entity.ToTable("product");
+
+ entity.Property(e => e.Id).HasColumnName("id");
+ entity.Property(e => e.Cost)
+ .HasPrecision(19, 4)
+ .HasColumnName("cost");
+ entity.Property(e => e.Description).HasColumnName("description");
+ entity.Property(e => e.Isactive).HasColumnName("isactive");
+ entity.Property(e => e.Mainimagepath)
+ .HasMaxLength(1000)
+ .HasColumnName("mainimagepath");
+ entity.Property(e => e.Manufacturerid).HasColumnName("manufacturerid");
+ entity.Property(e => e.Title)
+ .HasMaxLength(100)
+ .HasColumnName("title");
+
+ entity.HasOne(d => d.Manufacturer).WithMany(p => p.Products)
+ .HasForeignKey(d => d.Manufacturerid)
+ .HasConstraintName("fk_product_manufacturer");
+
+ entity.HasMany(d => d.Attachedproducts).WithMany(p => p.Mainproducts)
+ .UsingEntity>(
+ "Attachedproduct",
+ r => r.HasOne().WithMany()
+ .HasForeignKey("Attachedproductid")
+ .OnDelete(DeleteBehavior.ClientSetNull)
+ .HasConstraintName("fk_attachedproduct_product1"),
+ l => l.HasOne().WithMany()
+ .HasForeignKey("Mainproductid")
+ .OnDelete(DeleteBehavior.ClientSetNull)
+ .HasConstraintName("fk_attachedproduct_product"),
+ j =>
+ {
+ j.HasKey("Mainproductid", "Attachedproductid").HasName("attachedproduct_pkey");
+ j.ToTable("attachedproduct");
+ j.IndexerProperty("Mainproductid").HasColumnName("mainproductid");
+ j.IndexerProperty("Attachedproductid").HasColumnName("attachedproductid");
+ });
+
+ entity.HasMany(d => d.Mainproducts).WithMany(p => p.Attachedproducts)
+ .UsingEntity>(
+ "Attachedproduct",
+ r => r.HasOne().WithMany()
+ .HasForeignKey("Mainproductid")
+ .OnDelete(DeleteBehavior.ClientSetNull)
+ .HasConstraintName("fk_attachedproduct_product"),
+ l => l.HasOne().WithMany()
+ .HasForeignKey("Attachedproductid")
+ .OnDelete(DeleteBehavior.ClientSetNull)
+ .HasConstraintName("fk_attachedproduct_product1"),
+ j =>
+ {
+ j.HasKey("Mainproductid", "Attachedproductid").HasName("attachedproduct_pkey");
+ j.ToTable("attachedproduct");
+ j.IndexerProperty("Mainproductid").HasColumnName("mainproductid");
+ j.IndexerProperty("Attachedproductid").HasColumnName("attachedproductid");
+ });
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.HasKey(e => e.Id).HasName("productphoto_pkey");
+
+ entity.ToTable("productphoto");
+
+ entity.Property(e => e.Id).HasColumnName("id");
+ entity.Property(e => e.Photopath)
+ .HasMaxLength(1000)
+ .HasColumnName("photopath");
+ entity.Property(e => e.Productid).HasColumnName("productid");
+
+ entity.HasOne(d => d.Product).WithMany(p => p.Productphotos)
+ .HasForeignKey(d => d.Productid)
+ .OnDelete(DeleteBehavior.ClientSetNull)
+ .HasConstraintName("fk_productphoto_product");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.HasKey(e => e.Id).HasName("productsale_pkey");
+
+ entity.ToTable("productsale");
+
+ entity.Property(e => e.Id).HasColumnName("id");
+ entity.Property(e => e.Clientserviceid).HasColumnName("clientserviceid");
+ entity.Property(e => e.Productid).HasColumnName("productid");
+ entity.Property(e => e.Quantity).HasColumnName("quantity");
+ entity.Property(e => e.Saledate)
+ .HasColumnType("timestamp(6) without time zone")
+ .HasColumnName("saledate");
+
+ entity.HasOne(d => d.Clientservice).WithMany(p => p.Productsales)
+ .HasForeignKey(d => d.Clientserviceid)
+ .HasConstraintName("fk_productsale_clientservice");
+
+ entity.HasOne(d => d.Product).WithMany(p => p.Productsales)
+ .HasForeignKey(d => d.Productid)
+ .OnDelete(DeleteBehavior.ClientSetNull)
+ .HasConstraintName("fk_productsale_product");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.HasKey(e => e.Id).HasName("service_pkey");
+
+ entity.ToTable("service");
+
+ entity.Property(e => e.Id).HasColumnName("id");
+ entity.Property(e => e.Cost)
+ .HasPrecision(19, 4)
+ .HasColumnName("cost");
+ entity.Property(e => e.Description).HasColumnName("description");
+ entity.Property(e => e.Discount).HasColumnName("discount");
+ entity.Property(e => e.Durationinminutes).HasColumnName("durationinminutes");
+ entity.Property(e => e.Mainimagepath)
+ .HasMaxLength(1000)
+ .HasColumnName("mainimagepath");
+ entity.Property(e => e.Title)
+ .HasMaxLength(100)
+ .HasColumnName("title");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.HasKey(e => e.Id).HasName("servicephoto_pkey");
+
+ entity.ToTable("servicephoto");
+
+ entity.Property(e => e.Id).HasColumnName("id");
+ entity.Property(e => e.Photopath)
+ .HasMaxLength(1000)
+ .HasColumnName("photopath");
+ entity.Property(e => e.Serviceid).HasColumnName("serviceid");
+
+ entity.HasOne(d => d.Service).WithMany(p => p.Servicephotos)
+ .HasForeignKey(d => d.Serviceid)
+ .OnDelete(DeleteBehavior.ClientSetNull)
+ .HasConstraintName("fk_servicephoto_service");
+ });
+
+ modelBuilder.Entity(entity =>
+ {
+ entity.HasKey(e => e.Id).HasName("tag_pkey");
+
+ entity.ToTable("tag");
+
+ entity.Property(e => e.Id).HasColumnName("id");
+ entity.Property(e => e.Color)
+ .HasMaxLength(6)
+ .IsFixedLength()
+ .HasColumnName("color");
+ entity.Property(e => e.Title)
+ .HasMaxLength(30)
+ .HasColumnName("title");
+ });
+
+ OnModelCreatingPartial(modelBuilder);
+ }
+
+ partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
+}
diff --git a/ServiceApp/EntityModels/Manufacturer.cs b/ServiceApp/EntityModels/Manufacturer.cs
new file mode 100644
index 0000000..1bc90ea
--- /dev/null
+++ b/ServiceApp/EntityModels/Manufacturer.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+
+namespace ServiceApp.EnityModels;
+
+public partial class Manufacturer
+{
+ public int Id { get; set; }
+
+ public string Name { get; set; } = null!;
+
+ public DateOnly? Startdate { get; set; }
+
+ public virtual ICollection Products { get; set; } = new List();
+}
diff --git a/ServiceApp/EntityModels/Product.cs b/ServiceApp/EntityModels/Product.cs
new file mode 100644
index 0000000..ae2f5a7
--- /dev/null
+++ b/ServiceApp/EntityModels/Product.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+
+namespace ServiceApp.EnityModels;
+
+public partial class Product
+{
+ public int Id { get; set; }
+
+ public string Title { get; set; } = null!;
+
+ public decimal Cost { get; set; }
+
+ public string? Description { get; set; }
+
+ public string? Mainimagepath { get; set; }
+
+ public int Isactive { get; set; }
+
+ public int? Manufacturerid { get; set; }
+
+ public virtual Manufacturer? Manufacturer { get; set; }
+
+ public virtual ICollection Productphotos { get; set; } = new List();
+
+ public virtual ICollection Productsales { get; set; } = new List();
+
+ public virtual ICollection Attachedproducts { get; set; } = new List();
+
+ public virtual ICollection Mainproducts { get; set; } = new List();
+}
diff --git a/ServiceApp/EntityModels/Productphoto.cs b/ServiceApp/EntityModels/Productphoto.cs
new file mode 100644
index 0000000..1ed39c1
--- /dev/null
+++ b/ServiceApp/EntityModels/Productphoto.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+
+namespace ServiceApp.EnityModels;
+
+public partial class Productphoto
+{
+ public int Id { get; set; }
+
+ public int Productid { get; set; }
+
+ public string Photopath { get; set; } = null!;
+
+ public virtual Product Product { get; set; } = null!;
+}
diff --git a/ServiceApp/EntityModels/Productsale.cs b/ServiceApp/EntityModels/Productsale.cs
new file mode 100644
index 0000000..6967366
--- /dev/null
+++ b/ServiceApp/EntityModels/Productsale.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+
+namespace ServiceApp.EnityModels;
+
+public partial class Productsale
+{
+ public int Id { get; set; }
+
+ public DateTime Saledate { get; set; }
+
+ public int Productid { get; set; }
+
+ public int Quantity { get; set; }
+
+ public int? Clientserviceid { get; set; }
+
+ public virtual Clientservice? Clientservice { get; set; }
+
+ public virtual Product Product { get; set; } = null!;
+}
diff --git a/ServiceApp/EntityModels/Service.cs b/ServiceApp/EntityModels/Service.cs
new file mode 100644
index 0000000..b4ba8a6
--- /dev/null
+++ b/ServiceApp/EntityModels/Service.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+
+namespace ServiceApp.EnityModels;
+
+public partial class Service
+{
+ public int Id { get; set; }
+
+ public string Title { get; set; } = null!;
+
+ public decimal Cost { get; set; }
+
+ public int Durationinminutes { get; set; }
+
+ public string? Description { get; set; }
+
+ public double? Discount { get; set; }
+
+ public string? Mainimagepath { get; set; }
+
+ public virtual ICollection Clientservices { get; set; } = new List();
+
+ public virtual ICollection Servicephotos { get; set; } = new List();
+}
diff --git a/ServiceApp/EntityModels/Servicephoto.cs b/ServiceApp/EntityModels/Servicephoto.cs
new file mode 100644
index 0000000..f893773
--- /dev/null
+++ b/ServiceApp/EntityModels/Servicephoto.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+
+namespace ServiceApp.EnityModels;
+
+public partial class Servicephoto
+{
+ public int Id { get; set; }
+
+ public int Serviceid { get; set; }
+
+ public string Photopath { get; set; } = null!;
+
+ public virtual Service Service { get; set; } = null!;
+}
diff --git a/ServiceApp/EntityModels/Tag.cs b/ServiceApp/EntityModels/Tag.cs
new file mode 100644
index 0000000..a031485
--- /dev/null
+++ b/ServiceApp/EntityModels/Tag.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+
+namespace ServiceApp.EnityModels;
+
+public partial class Tag
+{
+ public int Id { get; set; }
+
+ public string Title { get; set; } = null!;
+
+ public string Color { get; set; } = null!;
+
+ public virtual ICollection Clients { get; set; } = new List();
+}
diff --git a/ServiceApp/MainWindow.axaml b/ServiceApp/MainWindow.axaml
new file mode 100644
index 0000000..ba7249c
--- /dev/null
+++ b/ServiceApp/MainWindow.axaml
@@ -0,0 +1,30 @@
+
+
+ Введите код для перехода в режим авдминистратора
+
+
+
+
+
+
+
diff --git a/ServiceApp/MainWindow.axaml.cs b/ServiceApp/MainWindow.axaml.cs
new file mode 100644
index 0000000..c4d69ee
--- /dev/null
+++ b/ServiceApp/MainWindow.axaml.cs
@@ -0,0 +1,27 @@
+using Avalonia.Controls;
+
+namespace ServiceApp
+{
+ public partial class MainWindow : Window
+ {
+ private string _secretCode = "0000";
+ public MainWindow()
+ {
+ InitializeComponent();
+ }
+
+ private void LoginClientButton_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
+ {
+ new ServiceWindow().Show();
+ this.Close();
+ }
+ private void LoginAdminButton_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
+ {
+ if (CodeTextBox.Text == _secretCode) {
+ new ServiceAdminWindow().Show();
+ this.Close();
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/ServiceApp/Program.cs b/ServiceApp/Program.cs
new file mode 100644
index 0000000..39fb0bf
--- /dev/null
+++ b/ServiceApp/Program.cs
@@ -0,0 +1,22 @@
+using Avalonia;
+using System;
+
+namespace ServiceApp
+{
+ 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) => BuildAvaloniaApp()
+ .StartWithClassicDesktopLifetime(args);
+
+ // Avalonia configuration, don't remove; also used by visual designer.
+ public static AppBuilder BuildAvaloniaApp()
+ => AppBuilder.Configure()
+ .UsePlatformDetect()
+ .WithInterFont()
+ .LogToTrace();
+ }
+}
diff --git a/ServiceApp/ServiceApp.csproj b/ServiceApp/ServiceApp.csproj
new file mode 100644
index 0000000..eec6d5e
--- /dev/null
+++ b/ServiceApp/ServiceApp.csproj
@@ -0,0 +1,39 @@
+
+
+ WinExe
+ net8.0
+ enable
+ true
+ app.manifest
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+ ServiceWindowAdmin.axaml
+
+
+
diff --git a/ServiceApp/ServiceWindow.axaml b/ServiceApp/ServiceWindow.axaml
new file mode 100644
index 0000000..f813513
--- /dev/null
+++ b/ServiceApp/ServiceWindow.axaml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+ Статистика
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ServiceApp/ServiceWindow.axaml.cs b/ServiceApp/ServiceWindow.axaml.cs
new file mode 100644
index 0000000..a28ac13
--- /dev/null
+++ b/ServiceApp/ServiceWindow.axaml.cs
@@ -0,0 +1,132 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using System.Linq;
+using ServiceApp.EnityModels;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using SkiaSharp;
+using Microsoft.EntityFrameworkCore.Storage.Json;
+using System;
+using Npgsql.TypeMapping;
+using Avalonia.Media.Imaging;
+using Avalonia.Platform;
+
+namespace ServiceApp;
+
+public partial class ServiceWindow : Window
+{
+ public List sourceList { get; set; }
+ public ObservableCollection displayList { get; }
+
+ private string _searchWord = string.Empty;
+
+ private string[] _sortingSource = new string[3] { ".", " .", " ." };
+ private Dictionary _dicountFilter = new Dictionary {
+ {"", (0, 0) },
+ { "0-5", (0,5)},
+ { "15-30", (5,15)},
+ { "30-70", (30,70)},
+ { "70-100", (70,100)},
+ };
+
+ public ServiceWindow()
+ {
+ InitializeComponent();
+ using (var dbContext = new IsajkinContext())
+ {
+
+ sourceList = dbContext.Services.Select(service =>
+ new ServicePresenter
+ {
+ Title = service.Title,
+ Discount = service.Discount,
+ Durationinminutes = service.Durationinminutes,
+ Id = service.Id,
+ Cost = service.Cost,
+ Mainimagepath = service.Mainimagepath,
+ }
+ ).ToList();
+ }
+ displayList = new ObservableCollection(sourceList);
+ SortingComboBox.ItemsSource = _sortingSource;
+ ServiceListBox.ItemsSource = displayList;
+ FilteringComboBox.ItemsSource = _dicountFilter.Keys;
+ StatisticTextBlock.Text = String.Format("{0} {1}", displayList.Count, sourceList.Count);
+
+ }
+
+ private void DisplayService() {
+
+ var displayServiceList = sourceList;
+ if (FilteringComboBox.SelectedIndex > 0) displayServiceList = displayServiceList.Where(service =>
+ FilterByDiscount(service, FilteringComboBox.SelectionBoxItem.ToString())).ToList();
+ if(!String.IsNullOrEmpty(_searchWord)) displayServiceList = displayServiceList.Where(service => SearchByWord(service, _searchWord)).ToList();
+ if(SortingComboBox.SelectedIndex > 0) displayServiceList = SortingComboBox.SelectedIndex == 1?
+ displayServiceList.OrderBy(service => service.Cost).ToList() :
+ displayServiceList.OrderByDescending(service => service.Cost).ToList();
+ displayList.Clear();
+ foreach (var service in displayServiceList) { displayList.Add(service); }
+ StatisticTextBlock.Text = String.Format("{0} {1}", displayServiceList.Count, sourceList.Count);
+ }
+
+
+ private bool SearchByWord(ServicePresenter service, string word) {
+ if (service.Title.Contains(word, StringComparison.CurrentCultureIgnoreCase)) return true;
+ if (String.IsNullOrEmpty(service.Description)) return false;
+ if (service.Description.Contains(word, StringComparison.CurrentCultureIgnoreCase)) return true;
+ return false;
+ }
+ private bool FilterByDiscount(ServicePresenter servicePresenter, string key) {
+ (int left, int right) = _dicountFilter[key];
+ double discount = servicePresenter.Discount != null? Convert.ToDouble(servicePresenter.Discount) * 100 : 0;
+ return left <= discount && discount < right;
+ }
+
+ private void SearchTextBox_TextChanged(object? sender, Avalonia.Controls.TextChangedEventArgs e)
+ {
+ _searchWord = SearchTextBox.Text.ToString();
+ DisplayService();
+ }
+
+
+ private void FilteringComboBox_SelectionChanged(object? sender, Avalonia.Controls.SelectionChangedEventArgs e)
+ {
+ DisplayService();
+ }
+
+ private void SortingComboBox_SelectionChanged(object? sender, Avalonia.Controls.SelectionChangedEventArgs e)
+ {
+ DisplayService();
+ }
+}
+
+public class ServicePresenter() : Service
+{
+ public int ServiceID { get => this.Id; }
+ public string ServiceName { get => this.Title; }
+ public string SeviceCostPerSeconds { get =>
+ (this.Discount != 0 ?
+ String.Format("{0:0.00} {1} ", this.Cost - this.Cost * Convert.ToDecimal(this.Discount), this.Durationinminutes)
+ :
+ String.Format("{0:0.00} {1} ", this.Cost, this.Durationinminutes)
+ );
+ }
+ public Bitmap ServiceImage { get => GetBitmap(this.Mainimagepath); }
+ public decimal? OldCost { get => (this.Discount != 0 ? this.Cost : null); }
+ public string? ServiceDiscount { get =>
+ (this.Discount != 0 ?
+ String.Format("* {0}%", Discount * 100)
+ : String.Empty
+ ); }
+
+ private Bitmap GetBitmap(string fileName) {
+ try {
+ return new Bitmap($"Assets\\{fileName}");
+ }
+ catch (Exception ex) {
+ return new Bitmap("Assets\\download.png");
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/ServiceApp/ServiceWindowAdmin.axaml b/ServiceApp/ServiceWindowAdmin.axaml
new file mode 100644
index 0000000..2e977a4
--- /dev/null
+++ b/ServiceApp/ServiceWindowAdmin.axaml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+ Статистика
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ServiceApp/ServiceWindowAdmin.axaml.cs b/ServiceApp/ServiceWindowAdmin.axaml.cs
new file mode 100644
index 0000000..58d87ea
--- /dev/null
+++ b/ServiceApp/ServiceWindowAdmin.axaml.cs
@@ -0,0 +1,134 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using System.Linq;
+using ServiceApp.EnityModels;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using SkiaSharp;
+using Microsoft.EntityFrameworkCore.Storage.Json;
+using System;
+using Npgsql.TypeMapping;
+using Avalonia.Media.Imaging;
+using Avalonia.Platform;
+
+namespace ServiceApp;
+
+public partial class ServiceAdminWindow : Window
+{
+ public List sourceList { get; set; }
+ public ObservableCollection displayList { get; }
+
+ private string _searchWord = string.Empty;
+
+ private string[] _sortingSource = new string[3] { ".", " .", " ." };
+ private Dictionary _dicountFilter = new Dictionary {
+ {"", (0, 0) },
+ { "0-5", (0,5)},
+ { "15-30", (5,15)},
+ { "30-70", (30,70)},
+ { "70-100", (70,100)},
+ };
+
+ public ServiceAdminWindow()
+ {
+ InitializeComponent();
+ using (var dbContext = new IsajkinContext())
+ {
+
+ sourceList = dbContext.Services.Select(service =>
+ new ServicePresenter
+ {
+ Title = service.Title,
+ Discount = service.Discount,
+ Durationinminutes = service.Durationinminutes,
+ Id = service.Id,
+ Cost = service.Cost,
+ Mainimagepath = service.Mainimagepath,
+ }
+ ).ToList();
+ }
+ displayList = new ObservableCollection(sourceList);
+ SortingComboBox.ItemsSource = _sortingSource;
+ ServiceListBox.ItemsSource = displayList;
+ FilteringComboBox.ItemsSource = _dicountFilter.Keys;
+ StatisticTextBlock.Text = String.Format("{0} {1}", displayList.Count, sourceList.Count);
+
+
+ }
+
+ private void DisplayService() {
+
+ var displayServiceList = sourceList;
+ if (FilteringComboBox.SelectedIndex > 0) displayServiceList = displayServiceList.Where(service =>
+ FilterByDiscount(service, FilteringComboBox.SelectionBoxItem.ToString())).ToList();
+ if(!String.IsNullOrEmpty(_searchWord)) displayServiceList = displayServiceList.Where(service => SearchByWord(service, _searchWord)).ToList();
+ if(SortingComboBox.SelectedIndex > 0) displayServiceList = SortingComboBox.SelectedIndex == 1?
+ displayServiceList.OrderBy(service => service.Cost).ToList() :
+ displayServiceList.OrderByDescending(service => service.Cost).ToList();
+ displayList.Clear();
+ foreach (var service in displayServiceList) { displayList.Add(service); }
+ StatisticTextBlock.Text = String.Format("{0} {1}", displayServiceList.Count, sourceList.Count);
+ }
+
+
+ private bool SearchByWord(ServicePresenter service, string word) {
+ if (service.Title.Contains(word, StringComparison.CurrentCultureIgnoreCase)) return true;
+ if (String.IsNullOrEmpty(service.Description)) return false;
+ if (service.Description.Contains(word, StringComparison.CurrentCultureIgnoreCase)) return true;
+ return false;
+ }
+ private bool FilterByDiscount(ServicePresenter servicePresenter, string key) {
+ (int left, int right) = _dicountFilter[key];
+ double discount = servicePresenter.Discount != null? Convert.ToDouble(servicePresenter.Discount) * 100 : 0;
+ return left <= discount && discount < right;
+ }
+
+ private void SearchTextBox_TextChanged(object? sender, Avalonia.Controls.TextChangedEventArgs e)
+ {
+ _searchWord = SearchTextBox.Text.ToString();
+ DisplayService();
+ }
+
+
+ private void FilteringComboBox_SelectionChanged(object? sender, Avalonia.Controls.SelectionChangedEventArgs e)
+ {
+ DisplayService();
+ }
+
+ private void SortingComboBox_SelectionChanged(object? sender, Avalonia.Controls.SelectionChangedEventArgs e)
+ {
+ DisplayService();
+ }
+
+ private void EditButton_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
+ {
+
+ }
+
+ private void RemoveButton_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
+ {
+ var serviceID = Convert.ToInt32((sender as Button).Tag);
+ using (var dbContext = new IsajkinContext()) {
+ var service = dbContext.Services.First(service => service.Id == serviceID);
+ var serviceLocal = displayList.First(service => service.Id == serviceID);
+ if (service == null) return;
+ if (dbContext.Clientservices.Where(item => item.Serviceid == serviceID).Count() > 0) return;
+ using var transaction = dbContext.Database.BeginTransaction();
+ try
+ {
+ if (dbContext.Servicephotos.Where(item => item.Serviceid == serviceID).Count() > 0)
+ {
+ dbContext.RemoveRange(dbContext.Servicephotos.Where(item => item.Serviceid == serviceID));
+ }
+ dbContext.Services.Remove(service);
+ displayList.Remove(serviceLocal);
+ dbContext.SaveChanges();
+ transaction.Commit();
+ }
+ catch (Exception ex) {
+
+ }
+ } ;
+ }
+}
diff --git a/ServiceApp/app.manifest b/ServiceApp/app.manifest
new file mode 100644
index 0000000..629772a
--- /dev/null
+++ b/ServiceApp/app.manifest
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+