Commit
This commit is contained in:
22
UP01Task2App/UP01Task2App/Models/Client.cs
Normal file
22
UP01Task2App/UP01Task2App/Models/Client.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace UP01Task2App.Models
|
||||||
|
{
|
||||||
|
public class Client
|
||||||
|
{
|
||||||
|
public string Surname { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Patronymic { get; set; }
|
||||||
|
public DateTime? BirthDate { get; set; }
|
||||||
|
public string Adress { get; set; }
|
||||||
|
public string PhoneNumber { get; set; }
|
||||||
|
public int SubscriptionNumber { get; set; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Surname + " " + Name + " " + Patronymic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
UP01Task2App/UP01Task2App/Models/Record.cs
Normal file
14
UP01Task2App/UP01Task2App/Models/Record.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace UP01Task2App.Models
|
||||||
|
{
|
||||||
|
public class Record
|
||||||
|
{
|
||||||
|
public Client Client { get; set; }
|
||||||
|
public Trainer Trainer { get; set; }
|
||||||
|
DateOnly RecordDate { set; get; }
|
||||||
|
TimeOnly RecordTime { set; get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
14
UP01Task2App/UP01Task2App/Models/Trainer.cs
Normal file
14
UP01Task2App/UP01Task2App/Models/Trainer.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace UP01Task2App.Models
|
||||||
|
{
|
||||||
|
public class Trainer
|
||||||
|
{
|
||||||
|
public string Surmname { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Patronymic { get; set; }
|
||||||
|
public string Speciality { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
71
UP01Task2App/UP01Task2App/Services/JsonService.cs
Normal file
71
UP01Task2App/UP01Task2App/Services/JsonService.cs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
using UP01Task2App.Models;
|
||||||
|
|
||||||
|
namespace UP01Task2App.Services
|
||||||
|
{
|
||||||
|
internal class JsonService
|
||||||
|
{
|
||||||
|
private const string trainerPath = "data/trainers.json";
|
||||||
|
private const string clientPath = "data/clients.json";
|
||||||
|
private const string recordPath = "data/records.json";
|
||||||
|
|
||||||
|
private void SaveToJson<T>(string path, List<T> data)
|
||||||
|
{
|
||||||
|
var options = new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
WriteIndented = true
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
data ??= new List<T>();
|
||||||
|
|
||||||
|
string json = JsonSerializer.Serialize(data, options);
|
||||||
|
|
||||||
|
string? dir = System.IO.Path.GetDirectoryName(path);
|
||||||
|
if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
|
||||||
|
Directory.CreateDirectory(dir);
|
||||||
|
|
||||||
|
File.WriteAllText(path, json, Encoding.UTF8);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Не удалось сохранить данные");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<T> ReadFromJson<T>(string path)
|
||||||
|
{
|
||||||
|
if (!File.Exists(path) || new FileInfo(path).Length == 0)
|
||||||
|
return new List<T>();
|
||||||
|
|
||||||
|
string json = File.ReadAllText(path);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(json))
|
||||||
|
return new List<T>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return JsonSerializer.Deserialize<List<T>>(json) ?? new List<T>();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return new List<T>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Trainer> ReadTrainerDataFromJson() => ReadFromJson<Trainer>(trainerPath);
|
||||||
|
public List<Client> ReadClientDataFromJson() => ReadFromJson<Client>(clientPath);
|
||||||
|
public List<Record> ReadRecordDataFromJson() => ReadFromJson<Record>(recordPath);
|
||||||
|
|
||||||
|
public void SaveTrainerDataToJson(List<Trainer> trainersList) => SaveToJson(trainerPath, trainersList);
|
||||||
|
public void SaveClientDataToJson(List<Client> clientsList) => SaveToJson(clientPath, clientsList);
|
||||||
|
public void SaveRecordDataToJson(List<Record> recordsList) => SaveToJson(recordPath, recordsList);
|
||||||
|
}
|
||||||
|
}
|
||||||
39
UP01Task2App/UP01Task2App/Services/ValidationHelper.cs
Normal file
39
UP01Task2App/UP01Task2App/Services/ValidationHelper.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
|
||||||
|
namespace UP01Task2App.Services
|
||||||
|
{
|
||||||
|
public static class ValidationHelper
|
||||||
|
{
|
||||||
|
public static void ValidateNotNullTextBox(TextBox obj, string fieldName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(obj.Text))
|
||||||
|
throw new ArgumentException($"Поле \"{fieldName}\" не должно быть пустым");
|
||||||
|
}
|
||||||
|
public static void ValidateNumTextBox(TextBox obj, string fieldName)
|
||||||
|
{
|
||||||
|
foreach (var c in obj.Text)
|
||||||
|
{
|
||||||
|
if (!char.IsDigit(c))
|
||||||
|
throw new ArgumentException($"В поле \"{fieldName}\" можно вводить только числа");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void ValidateDateNotInFutureTextBox(DatePicker obj, string fieldName)
|
||||||
|
{
|
||||||
|
if (obj.SelectedDate > DateTime.Now)
|
||||||
|
throw new ArgumentException($"В поле \"{fieldName}\" выбранная дата не может быть в будущем");
|
||||||
|
}
|
||||||
|
public static void ValidateNotNullDatePicker(DatePicker obj, string fieldName)
|
||||||
|
{
|
||||||
|
if (obj.SelectedDate == null)
|
||||||
|
throw new ArgumentException($"Выберите дату в поле \"{fieldName}\"");
|
||||||
|
}
|
||||||
|
public static void ValidateIntRangeTextBox(TextBox obj, string fieldName)
|
||||||
|
{
|
||||||
|
if (!int.TryParse(obj.Text, out int _))
|
||||||
|
throw new ArgumentException($"Введенное число в \"{fieldName}\" слишком большое или маленькое");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace UP01Task2App.ViewModels
|
|
||||||
{
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
public class BaseViewModel : INotifyPropertyChanged
|
|
||||||
{
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
|
||||||
|
|
||||||
protected void OnPropertyChanged([CallerMemberName] string name = null)
|
|
||||||
{
|
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Windows.Input;
|
|
||||||
|
|
||||||
public class RelayCommand : ICommand
|
|
||||||
{
|
|
||||||
private readonly Action _execute;
|
|
||||||
private readonly Func<bool> _canExecute;
|
|
||||||
|
|
||||||
public RelayCommand(Action execute, Func<bool> canExecute = null)
|
|
||||||
{
|
|
||||||
_execute = execute;
|
|
||||||
_canExecute = canExecute;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CanExecute(object parameter) => _canExecute?.Invoke() ?? true;
|
|
||||||
|
|
||||||
public void Execute(object parameter) => _execute();
|
|
||||||
|
|
||||||
public event EventHandler CanExecuteChanged;
|
|
||||||
}
|
|
||||||
@@ -11,32 +11,32 @@
|
|||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<StackPanel HorizontalAlignment="Left">
|
<StackPanel HorizontalAlignment="Left">
|
||||||
<TextBlock Text="Фамилия"/>
|
<TextBlock Text="Фамилия"/>
|
||||||
<TextBox Text="{Binding LastName}" Style="{StaticResource TextBoxStyle}"/>
|
<TextBox Name="SurnameTextBox" Style="{StaticResource TextBoxStyle}"/>
|
||||||
|
|
||||||
<TextBlock Text="Имя"/>
|
<TextBlock Text="Имя"/>
|
||||||
<TextBox Text="{Binding FirstName}" Style="{StaticResource TextBoxStyle}"/>
|
<TextBox Name="NameTextBox" Style="{StaticResource TextBoxStyle}"/>
|
||||||
|
|
||||||
<TextBlock Text="Отчество"/>
|
<TextBlock Text="Отчество"/>
|
||||||
<TextBox Text="{Binding MiddleName}" Style="{StaticResource TextBoxStyle}"/>
|
<TextBox Name="PatronymicTextBox" Style="{StaticResource TextBoxStyle}"/>
|
||||||
|
|
||||||
<TextBlock Text="Дата рождения"/>
|
<TextBlock Text="Дата рождения"/>
|
||||||
<DatePicker SelectedDate="{Binding BirthDate}" Style="{StaticResource DatePickerStyle}" />
|
<DatePicker Name="BirthDateDatePicker" Style="{StaticResource DatePickerStyle}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<StackPanel HorizontalAlignment="Right" Margin="20,0,0,0">
|
<StackPanel HorizontalAlignment="Right" Margin="20,0,0,0">
|
||||||
<TextBlock Text="Фактический адрес"/>
|
<TextBlock Text="Фактический адрес"/>
|
||||||
<TextBox Text="{Binding Address}" Style="{StaticResource TextBoxStyle}"/>
|
<TextBox Name="AdressTextBox" Style="{StaticResource TextBoxStyle}"/>
|
||||||
|
|
||||||
<TextBlock Text="Телефон"/>
|
<TextBlock Text="Телефон"/>
|
||||||
<TextBox Text="{Binding Phone}" Style="{StaticResource TextBoxStyle}"/>
|
<TextBox Name="PhoneNumberTextBox" Style="{StaticResource TextBoxStyle}"/>
|
||||||
|
|
||||||
<TextBlock Text="Номер абонемента"/>
|
<TextBlock Text="Номер абонемента"/>
|
||||||
<TextBox Text="{Binding MembershipNumber}" Style="{StaticResource TextBoxStyle}"/>
|
<TextBox Name="SubscriptionMumberTextBox" Style="{StaticResource TextBoxStyle}"/>
|
||||||
|
|
||||||
<TextBlock Text="Пол"/>
|
<TextBlock Text="Пол"/>
|
||||||
<StackPanel Orientation="Horizontal" Margin="5">
|
<StackPanel Orientation="Horizontal" Margin="5">
|
||||||
<RadioButton Content="М" GroupName="rg1"/>
|
<RadioButton Name="rbMan" Content="М" GroupName="rg1"/>
|
||||||
<RadioButton Content="Ж" GroupName="rg1"/>
|
<RadioButton Name="rbWoman" Content="Ж" GroupName="rg1"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
@@ -47,33 +47,27 @@
|
|||||||
|
|
||||||
<TextBlock Text="Список клиентов" FontSize="18" Margin="0,0,0,10"/>
|
<TextBlock Text="Список клиентов" FontSize="18" Margin="0,0,0,10"/>
|
||||||
|
|
||||||
<ListBox ItemsSource="{Binding Clients}"
|
<ListBox ItemsSource="{Binding ClientsUI}"
|
||||||
SelectedItem="{Binding SelectedClient}"
|
Height="250"/>
|
||||||
Height="250"
|
|
||||||
DisplayMemberPath="LastName"/>
|
|
||||||
|
|
||||||
<StackPanel Orientation="Horizontal"
|
<StackPanel Orientation="Horizontal"
|
||||||
Margin="10">
|
Margin="10">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<Button Content="Добавить клиента"
|
<Button Content="Добавить клиента"
|
||||||
Command="{Binding AddClientCommand}"
|
|
||||||
Style="{StaticResource ButtonStyle}"
|
Style="{StaticResource ButtonStyle}"
|
||||||
Margin="10"/>
|
Margin="10" Click="Button_Click"/>
|
||||||
|
|
||||||
<Button Content="Изменить клиента"
|
<Button Content="Изменить клиента"
|
||||||
Command="{Binding EditClientCommand}"
|
|
||||||
Style="{StaticResource ButtonStyle}"
|
Style="{StaticResource ButtonStyle}"
|
||||||
Margin="10"/>
|
Margin="10"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<Button Content="Запись клиента"
|
<Button Content="Запись клиента"
|
||||||
Command="{Binding AddAppointmentCommand}"
|
|
||||||
Style="{StaticResource ButtonStyle}"
|
Style="{StaticResource ButtonStyle}"
|
||||||
Margin="10"/>
|
Margin="10"/>
|
||||||
|
|
||||||
<Button Content="Просмотреть записи"
|
<Button Content="Просмотреть записи"
|
||||||
Command="{Binding ViewAppointmentsCommand}"
|
|
||||||
Style="{StaticResource ButtonStyle}"
|
Style="{StaticResource ButtonStyle}"
|
||||||
Margin="10"/>
|
Margin="10"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
@@ -9,6 +12,8 @@ using System.Windows.Input;
|
|||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using System.Windows.Shapes;
|
using System.Windows.Shapes;
|
||||||
|
using UP01Task2App.Models;
|
||||||
|
using UP01Task2App.Services;
|
||||||
|
|
||||||
namespace UP01Task2App.Windows
|
namespace UP01Task2App.Windows
|
||||||
{
|
{
|
||||||
@@ -17,9 +22,91 @@ namespace UP01Task2App.Windows
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class ClientWindow : Window
|
public partial class ClientWindow : Window
|
||||||
{
|
{
|
||||||
|
private JsonService Json = new();
|
||||||
|
public List<Client> ClientsList = new();
|
||||||
|
public List<Trainer> TrainersList = new();
|
||||||
|
public List<Record> RecordsList = new();
|
||||||
|
|
||||||
|
public ObservableCollection<Client> ClientsUI { get; set; } = new();
|
||||||
public ClientWindow()
|
public ClientWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
|
ClientsList = Json.ReadClientDataFromJson();
|
||||||
|
TrainersList = Json.ReadTrainerDataFromJson();
|
||||||
|
RecordsList = Json.ReadRecordDataFromJson();
|
||||||
|
|
||||||
|
UpdateClientUI();
|
||||||
|
|
||||||
|
this.DataContext = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateClientUI()
|
||||||
|
{
|
||||||
|
ClientsUI.Clear();
|
||||||
|
foreach (var item in ClientsList)
|
||||||
|
{
|
||||||
|
ClientsUI.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ValidateFields()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ValidationHelper.ValidateNotNullTextBox(SurnameTextBox, "Фамилия");
|
||||||
|
ValidationHelper.ValidateNotNullTextBox(NameTextBox, "Имя");
|
||||||
|
ValidationHelper.ValidateNotNullTextBox(PatronymicTextBox, "Отчество");
|
||||||
|
ValidationHelper.ValidateNotNullDatePicker(BirthDateDatePicker, "Дата рождения");
|
||||||
|
ValidationHelper.ValidateDateNotInFutureTextBox(BirthDateDatePicker, "Дата рождения");
|
||||||
|
ValidationHelper.ValidateNotNullTextBox(AdressTextBox, "Фактический адрес");
|
||||||
|
ValidationHelper.ValidateNotNullTextBox(PhoneNumberTextBox, "Телефон");
|
||||||
|
ValidationHelper.ValidateNumTextBox(PhoneNumberTextBox, "Телефон");
|
||||||
|
ValidationHelper.ValidateNotNullTextBox(SubscriptionMumberTextBox, "Номер абонемента");
|
||||||
|
ValidationHelper.ValidateNumTextBox(SubscriptionMumberTextBox, "Номер абонемента");
|
||||||
|
ValidationHelper.ValidateIntRangeTextBox(SubscriptionMumberTextBox, "Номер абонемента");
|
||||||
|
|
||||||
|
if (rbMan.IsChecked == null && rbWoman.IsChecked == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Выберите пол");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show(ex.Message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Button_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (ValidateFields())
|
||||||
|
{
|
||||||
|
ClientsList.Add(new Client
|
||||||
|
{
|
||||||
|
Surname = SurnameTextBox.Text,
|
||||||
|
Name = NameTextBox.Text,
|
||||||
|
Adress = AdressTextBox.Text,
|
||||||
|
BirthDate = BirthDateDatePicker.SelectedDate,
|
||||||
|
Patronymic = PatronymicTextBox.Text,
|
||||||
|
PhoneNumber = PhoneNumberTextBox.Text,
|
||||||
|
SubscriptionNumber = int.Parse(SubscriptionMumberTextBox.Text)
|
||||||
|
});
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Json.SaveClientDataToJson(ClientsList);
|
||||||
|
MessageBox.Show("Данные сохранены");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show(ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateClientUI();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user