)8r&*L3PA
zGNYd+_^;nNKmTI~dY_~zXvYtC&`V1XP`{HN)&XeWGrj5UlH
zZee!1VNvH+5`n^X)VT_uHU@y|7KTyy(Z?5qDg$KFEcW)=_8v;X0rL`a)!hGn@n}0a
z!pymqFnJDNAMzAKwQ-_dH6PqoTW*@0bIGbgg_4V*9x0{sQ*CWmB{
zCeF05wqYfu%aUy;K=dliZ4bLVR6F%cgcF4tU#>fXa5Jho-GFog`9%anGa*?tt#`gv51zbJFbZpG+=eKbo&brl>piU(=FUrL*v%^1KT3SwBH<`1;$<}htc5GWLgY8n5X8dRx6S|dRbF$(&MAHwb{23GZb^tG;PV4|Q)OA)CH&$x5x
z^6A@po{orr<=f}~?N`B}df>Ti>g_7WArV5DI`Trc&QEbgq*`4VnY)=@(#yaHX^V!r
zbo+-j2rVb$%#S2pGbKPbZ)8D`hqBPEdT+)>YFSB!-rhmAHjS!yyDInZtEXnXt^9c&
zU)dIgeaii;y+7{#f=8PD`~G#$CK0;|*4f0gy~S5`iK?oCG{r%CriEw#NZIGH=7QR8
zwmXwIhA$ili;#J>xLoOKaP)Xx0ZSNmFV68J@XqI6eE>l8x?q>`Q1BaA`9;IOAqO)Y
z`-g#*1AQlkop833=9a0X_WK<)qZ$4u4Kb|@w!~L`Kl_u!og!QcNMFlRtpK%V#zEKd
z9`F?8_RCfii3E^sbSIuY$PbLg3^0qTd6?^*Bz<#w{WGw(NzIxBoM71GHc$F_CCDK|
zD#O*CdpRM40kPB2W;pi&D?_|p-{Y}rB&9furJCJ_BzE`$JErD%1mj7dvytXv}NCML!)g&Fjnqns32!WA~{ZIEY3HLstQ&@55lm4W9r
zQF(g9g`z+N>UVvVsPLmnVA?8(2_dO
z@L(I;NA&Ec9)Nbkw?FG>EBUA2@XihhLMM6rL>=%s8qRV|uI%V6lvM?QfYjKZNS|Ne
z@78l?1G?&t4{^)ENK2xK9-^CxwB?9mAkdc%%1EHnd8G1N0Rx7HNbkuA0ba0V=rQ|
zVt>}Ta!mPuQ*+dDGRjJrDviGR48=Gk`%;Ca(=GQWony#EsRSr4;h~H`q$FGGaq`mN
z0DwZyyop0a|BGgrb+rK1qj#R9I2IGM%G8Jw<__NI>4HDVRC~a2h=Fb1ySb^RuQnM?
zJ4NxA<&_KVpg$Q>{)&?0%8FaV9hs%j;5pnz`j@|
zF+1rzyYz;z)9R%&42Qrj!I$v5PVFLfoL_LiQNw592kSC){6wLA+e`Y)Kxg84j{{>^
z@Z>0DC{e%GEP30%6e1XUbqvGae@NgNFM#IANo)k9cIRnP-}2$Yx*)!`Vk9l^-8)cP
zbY|#7f5HzI1};cY`6te0UR6Bp21_DRC34xzXpi|
zd63C~WVSvzthcq09*E%CyU6+|`bK3=%OTX>jFE2Cv4prn?R7&_dm--vM@dpBJi_mq
zff)M+PtK_~`vdAUqM7?cEAYVSESgJG*9K!B(QuN(-rmuxDofgKzfwBSp#PE|i(
zB;r7|D`RL7DZAc1t6Ur|vjKR`Jfw?^hWMopf~-gQb_x5M1Bd`AN?j}mkil!@f6Cn4
zo^(kIJJT5f8>jS-@>C~RTUjq%Edd5k=8o24R>e6rvl}U*Gj1E}%(c#9YC)K2;)Trs
zq1nhdW{%?n(#N^m<~mF`kvf}pW`$g*_-vMub%IZmE_Zz`Z~LzAp|PFSF46Q0+L?eU
zR9$s;^ePI#%Eh~$YwrMF2%E8g_lj`$RA*aOdZ6y51jvXoae&
z&i=gm4N$PP190>KO=ySBI<3uU@~?j8aF6-P@(kdyNFtz0JJ
zQ@%~Rl~vh9BsPFaVx^8aBBs&?T1d$$O78P%*=>GKEscN{@TSS`R^UVF%CXENN5$-)
ztYD0$Pz_a8b&dZ5YZd5+V28!WW!rA%fHsPh1k_cXku)*^;*L@u-|&T!^q3D{4?EHe
zK`Q&3!#AC|mIlEvzH}U8#w_p{EireN{skqK?Z3u}3^X8oCBHD&YyjY6pz}z`5pH38
z`fCpsLtbJ}KJQ(l_yt&!v^NYa&BvR5M7Iuzzhwf7T7=3*5kb
zYI}2TTe$^U(|^zAgOd$Qz*lFSpXRFHRhyk~u1me9r}ovMMw}xFwJIB1r0*WvO&A`}
zlHG08^aKdiACDQy$Ay}7Wi^YD^o>GJ5t>qLbrr|i?!K1$pVTQGzy4q+1TaO$(ovhX
zR8#g&(wwt{iDdO;u5r~Cj@DMeADcP(r=~LxypIWCH|VxDptC+>)vkwnk6*{CpZt;0
z>r>E773uH3AwL-RMhguH@ss@v=!CraOe|&YSELx2p1#dk!*`?kM9}#ADJp8)Nczyk
zo(~iWwwo=&)!^Z6(ZmY0I_r3P3o@MB1R7AEOT$*{j?0&=1^AhK7%)(@!weecbiwV0
z9;_g7!s+uKnhsNoXWW$nJOOZie~j}
zpDKFj?*H11EuU9S5M7kLFt`JxBTCtip}2mW%?=k_?(|to{=WMcTyTFwcpzi
zJ-Kqr`U#W%OgLK0)o;83=hbeGs9^Tdp~>1{!aOp^N5O+YQmyR3bY7N3bVtM0PXol)wjH7(C45kZYIsHj3}AV89^$9?~Ifmv%UpAd}6EvRuc@8pyq
zOpUe-bn@WX#DNrWFv6`pYgl{5C!dEw>`l`c#OC0pctZzPs8sN^vu7>n%E@{IxCX(>
zT*4$DiDgPB(Qe$DsJlf5?x0Y@eDL83eoHvn6-pp+?GzwIK+4XMnd*D
zq~MsiUX(y%+nC=i8p3g#RJAwQUK#S>>Wn+e=r}(li)P~i!*njngB8oys<#G9yj{xx
zU`wzWHOydZ>`Y)%A0o4m1$K%_Az$=B{O~txVgyUdM^*tZz+KfeXe9L1A$VU=5U5IK_-l
zR#^ENCit=Le$l?XGlXLyF!`@f_hq)x
+
+ WinExe
+ net8.0
+ enable
+ app.manifest
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+ None
+ All
+
+
+
+
+
+
+
+
+ Always
+
+
+
diff --git a/AutoService/Models/Service.cs b/AutoService/Models/Service.cs
new file mode 100644
index 0000000..d87291f
--- /dev/null
+++ b/AutoService/Models/Service.cs
@@ -0,0 +1,8 @@
+namespace AutoService.Models;
+
+public class Service
+{
+ public int Id { get; set; }
+ public string Title { get; set; }
+ public string Description { get; set; }
+}
\ No newline at end of file
diff --git a/AutoService/Program.cs b/AutoService/Program.cs
new file mode 100644
index 0000000..800c089
--- /dev/null
+++ b/AutoService/Program.cs
@@ -0,0 +1,42 @@
+using Avalonia;
+using System;
+using AutoService.Services;
+using AutoService.ViewModels;
+using AutoService.Views;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+
+namespace AutoService;
+
+sealed class Program
+{
+ [STAThread]
+ public static void Main(string[] args)
+ {
+ var host = Host.CreateDefaultBuilder(args)
+ .ConfigureAppConfiguration((hostingContext, config) =>
+ {
+ config.SetBasePath(AppContext.BaseDirectory).AddJsonFile("appsettings.json").AddEnvironmentVariables();
+ })
+ .ConfigureServices((context, services) =>
+ {
+ services.Configure(context.Configuration.GetSection("DatabaseSettings"));
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ }).Build();
+
+ BuildAvaloniaApp(host.Services)
+ .StartWithClassicDesktopLifetime(args);
+ }
+
+
+
+ // Avalonia configuration, don't remove; also used by visual designer.
+ public static AppBuilder BuildAvaloniaApp(IServiceProvider hostServices)
+ => AppBuilder.Configure(() => new App(hostServices))
+ .UsePlatformDetect()
+ .WithInterFont()
+ .LogToTrace();
+}
\ No newline at end of file
diff --git a/AutoService/Services/BaseRepository.cs b/AutoService/Services/BaseRepository.cs
new file mode 100644
index 0000000..bb27b9c
--- /dev/null
+++ b/AutoService/Services/BaseRepository.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using Microsoft.Extensions.Options;
+using MySqlConnector;
+
+namespace AutoService.Services;
+
+public abstract class BaseRepository : IDisposable
+{
+ private readonly DatabaseSettings _dbSettings;
+ protected MySqlConnection connection;
+
+ public BaseRepository(IOptions options)
+ {
+ _dbSettings = options.Value;
+ connection = new MySqlConnection(_dbSettings.ConnectionString);
+ }
+
+ public bool OpenConnection()
+ {
+ try
+ {
+ connection.Open();
+ return true;
+ }
+ catch (MySqlException ex)
+ {
+ Console.WriteLine(ex.Message);
+ return false;
+ }
+ }
+
+ public bool CloseConnection()
+ {
+ try
+ {
+ connection.Close();
+ return true;
+ }
+ catch (MySqlException ex)
+ {
+ Console.WriteLine(ex.Message);
+ return false;
+ }
+ }
+
+ public bool ExecuteNonQuery(string query)
+ {
+ using var cmd = new MySqlCommand(query, connection);
+ return cmd.ExecuteNonQuery() > 0;
+ }
+
+ public void Dispose()
+ {
+ connection.Dispose();
+ }
+}
\ No newline at end of file
diff --git a/AutoService/Services/DatabaseSettings.cs b/AutoService/Services/DatabaseSettings.cs
new file mode 100644
index 0000000..c359daf
--- /dev/null
+++ b/AutoService/Services/DatabaseSettings.cs
@@ -0,0 +1,6 @@
+namespace AutoService.Services;
+
+public class DatabaseSettings
+{
+ public string ConnectionString { get; set; }
+}
\ No newline at end of file
diff --git a/AutoService/Services/IServiceRepository.cs b/AutoService/Services/IServiceRepository.cs
new file mode 100644
index 0000000..379381a
--- /dev/null
+++ b/AutoService/Services/IServiceRepository.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+using AutoService.Models;
+
+namespace AutoService.Services;
+
+public interface IServiceRepository
+{
+ public IEnumerable GetAll();
+}
\ No newline at end of file
diff --git a/AutoService/Services/ServiceRepository.cs b/AutoService/Services/ServiceRepository.cs
new file mode 100644
index 0000000..389898a
--- /dev/null
+++ b/AutoService/Services/ServiceRepository.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using AutoService.Models;
+using Microsoft.Extensions.Options;
+using MySqlConnector;
+
+namespace AutoService.Services;
+
+public class ServiceRepository: BaseRepository, IServiceRepository, IDisposable
+{
+ private static List Services = new List();
+
+ public ServiceRepository(IOptions options) :base(options)
+ {
+ OpenConnection();
+
+ LoadServices();
+ }
+
+ public IEnumerable GetAll()
+ {
+ return Services;
+ }
+
+ private void LoadServices()
+ {
+ var cmd = new MySqlCommand("SELECT * FROM services", connection);
+
+ using (var reader = cmd.ExecuteReader())
+ {
+ while (reader.Read())
+ {
+ var test = new Service
+ {
+ Id = reader.GetInt32("Id"),
+ Title = reader.GetString("Title"),
+ Description = reader.GetString("Description"),
+ };
+ Services.Add(test);
+ }
+ }
+ }
+
+ public void Dispose()
+ {
+ CloseConnection();
+ base.Dispose();
+ }
+}
\ No newline at end of file
diff --git a/AutoService/ViewLocator.cs b/AutoService/ViewLocator.cs
new file mode 100644
index 0000000..146d06a
--- /dev/null
+++ b/AutoService/ViewLocator.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using Avalonia.Controls;
+using Avalonia.Controls.Templates;
+using AutoService.ViewModels;
+
+namespace AutoService;
+
+///
+/// Given a view model, returns the corresponding view if possible.
+///
+[RequiresUnreferencedCode(
+ "Default implementation of ViewLocator involves reflection which may be trimmed away.",
+ Url = "https://docs.avaloniaui.net/docs/concepts/view-locator")]
+public class ViewLocator : IDataTemplate
+{
+ public Control? Build(object? param)
+ {
+ if (param is null)
+ return null;
+
+ var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal);
+ var type = Type.GetType(name);
+
+ if (type != null)
+ {
+ return (Control)Activator.CreateInstance(type)!;
+ }
+
+ return new TextBlock { Text = "Not Found: " + name };
+ }
+
+ public bool Match(object? data)
+ {
+ return data is ViewModelBase;
+ }
+}
\ No newline at end of file
diff --git a/AutoService/ViewModels/MainWindowViewModel.cs b/AutoService/ViewModels/MainWindowViewModel.cs
new file mode 100644
index 0000000..3315b7e
--- /dev/null
+++ b/AutoService/ViewModels/MainWindowViewModel.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+using System.Linq;
+using AutoService.Models;
+using AutoService.Services;
+using CommunityToolkit.Mvvm.ComponentModel;
+
+namespace AutoService.ViewModels;
+
+public partial class MainWindowViewModel : ViewModelBase
+{
+ private IServiceRepository _iServiceRepository;
+
+ [ObservableProperty]
+ private string _client;
+
+ [ObservableProperty]
+ private string _auto;
+
+ [ObservableProperty]
+ private List _services;
+
+ [ObservableProperty]
+ private Service _selectedService;
+
+ public MainWindowViewModel(IServiceRepository serviceRepository)
+ {
+ _iServiceRepository = serviceRepository;
+
+ Services = _iServiceRepository.GetAll().ToList();
+ }
+}
\ No newline at end of file
diff --git a/AutoService/ViewModels/ViewModelBase.cs b/AutoService/ViewModels/ViewModelBase.cs
new file mode 100644
index 0000000..852e858
--- /dev/null
+++ b/AutoService/ViewModels/ViewModelBase.cs
@@ -0,0 +1,7 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+
+namespace AutoService.ViewModels;
+
+public abstract class ViewModelBase : ObservableObject
+{
+}
\ No newline at end of file
diff --git a/AutoService/Views/MainWindow.axaml b/AutoService/Views/MainWindow.axaml
new file mode 100644
index 0000000..b7e3616
--- /dev/null
+++ b/AutoService/Views/MainWindow.axaml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AutoService/Views/MainWindow.axaml.cs b/AutoService/Views/MainWindow.axaml.cs
new file mode 100644
index 0000000..8cdad65
--- /dev/null
+++ b/AutoService/Views/MainWindow.axaml.cs
@@ -0,0 +1,13 @@
+using AutoService.ViewModels;
+using Avalonia.Controls;
+
+namespace AutoService.Views;
+
+public partial class MainWindow : Window
+{
+ public MainWindow(MainWindowViewModel viewModel)
+ {
+ InitializeComponent();
+ DataContext = viewModel;
+ }
+}
\ 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/appsettings.json b/AutoService/appsettings.json
new file mode 100644
index 0000000..5c0e413
--- /dev/null
+++ b/AutoService/appsettings.json
@@ -0,0 +1,6 @@
+{
+ "DatabaseSettings":
+ {
+ "ConnectionString": "Server=192.168.200.13;Database=auto_service_db;User Id=student;Password=student;"
+ }
+}
\ No newline at end of file