-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAddEditReservationForm.cs
More file actions
246 lines (203 loc) · 9.63 KB
/
AddEditReservationForm.cs
File metadata and controls
246 lines (203 loc) · 9.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsAdminApp
{
public partial class AddEditReservationForm : Form
{
private readonly bool isEdit;
private readonly int? reservationId;
private readonly TextBox txtName;
private readonly TextBox txtEmail;
private readonly TextBox txtPhone;
private readonly DateTimePicker dpDate;
//private readonly DateTimePicker tpTime;
private ComboBox cbTime;
private readonly NumericUpDown numGuests;
private readonly TextBox txtMessage;
private readonly Button btnSave;
private readonly Button btnCancel;
public AddEditReservationForm(bool isEdit = false, int? reservationId = null,
string? name = null, string? email = null, string? phone = null,
DateTime? date = null, TimeSpan? time = null, int guests = 1, string? message = null)
{
this.isEdit = isEdit;
this.reservationId = reservationId;
Text = isEdit ? "Редактировать бронирование" : "Добавить бронирование";
Width = 400;
Height = 450;
StartPosition = FormStartPosition.CenterParent;
Label lbl1 = new() { Text = "Имя:", Left = 20, Top = 20 };
txtName = new() { Left = 120, Top = 20, Width = 220, Text = name ?? "" };
Label lbl2 = new() { Text = "Email:", Left = 20, Top = 60 };
txtEmail = new() { Left = 120, Top = 60, Width = 220, Text = email ?? "" };
Label lbl3 = new() { Text = "Телефон:", Left = 20, Top = 100 };
txtPhone = new() { Left = 120, Top = 100, Width = 220, Text = phone ?? "" };
Label lbl4 = new() { Text = "Дата:", Left = 20, Top = 140 };
dpDate = new() { Left = 120, Top = 140, Width = 220, Value = date ?? DateTime.Today };
Label lbl5 = new() { Text = "Время:", Left = 20, Top = 180 };
//tpTime = new() { Left = 120, Top = 180, Width = 150, Format = DateTimePickerFormat.Time, ShowUpDown = true };
//if (time != null) tpTime.Value = DateTime.Today.Add(time.Value);
cbTime = new ComboBox
{
Left = 120,
Top = 180,
Width = 80,
DropDownStyle = ComboBoxStyle.DropDownList
};
dpDate.ValueChanged += async (s, e) => await LoadAvailableTimes(dpDate.Value);
Controls.Add(cbTime);
_ = LoadAvailableTimes(dpDate.Value);
Label lbl6 = new() { Text = "Гостей:", Left = 20, Top = 220 };
numGuests = new() { Left = 120, Top = 220, Width = 80, Minimum = 1, Maximum = 50, Value = guests };
Label lbl7 = new() { Text = "Сообщение:", Left = 20, Top = 260 };
txtMessage = new() { Left = 20, Top = 280, Width = 320, Height = 60, Multiline = true, Text = message ?? "" };
btnSave = new() { Text = "Сохранить", Left = 80, Top = 360, Width = 100 };
btnCancel = new() { Text = "Отмена", Left = 200, Top = 360, Width = 100 };
btnCancel.Click += (s, e) => Close();
btnSave.Click += async (s, e) => await SaveReservation();
Controls.AddRange(new Control[] {
lbl1, txtName, lbl2, txtEmail, lbl3, txtPhone,
lbl4, dpDate, lbl5, cbTime, lbl6, numGuests,
lbl7, txtMessage, btnSave, btnCancel
});
}
private async Task LoadAvailableTimes(DateTime date)
{
cbTime.Items.Clear();
// Все возможные слоты, с 12:00 до 22:00
var allSlots = new List<TimeSpan>();
for (int h = 12; h <= 22; h++)
{
allSlots.Add(new TimeSpan(h, 0, 0));
//allSlots.Add(new TimeSpan(h, 30, 0)); добавление слотов 30 минут шаг
}
try
{
using var http = new HttpClient();
var url = AppConfig.ApiBaseUrl.TrimEnd('/') + "/api/reservations";
var resp = await http.GetAsync(url);
if (!resp.IsSuccessStatusCode)
{
MessageBox.Show("Не удалось получить бронирования.");
return;
}
var json = await resp.Content.ReadAsStringAsync();
var reservations = JsonSerializer.Deserialize<List<ReservationDto>>(json, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
// Получаем все занятые слоты на выбранную дату
var reservedTimes = reservations!
.Where(r => r.ReservationDate.Date == date.Date)
.Select(r => r.ReservationTime)
.ToHashSet();
// Фильтруем свободные слоты
var freeSlots = allSlots
.Where(t => !reservedTimes.Contains(t))
.OrderBy(t => t)
.ToList();
foreach (var t in freeSlots)
cbTime.Items.Add(t.ToString(@"hh\:mm"));
if (cbTime.Items.Count > 0)
cbTime.SelectedIndex = 0;
else
MessageBox.Show("На выбранную дату нет свободных слотов.");
}
catch (Exception ex)
{
MessageBox.Show("Ошибка загрузки времени: " + ex.Message);
}
}
private async Task SaveReservation()
{
if (string.IsNullOrWhiteSpace(txtName.Text))
{
MessageBox.Show("Введите имя");
return;
}
var selectedDateTime = dpDate.Value.Date + dpDate.Value.TimeOfDay;
if (selectedDateTime < DateTime.Now)
{
MessageBox.Show("Нельзя выбрать прошлое время!");
return;
}
using var http = new HttpClient();
var url = AppConfig.ApiBaseUrl.TrimEnd('/') + "/api/reservations";
var reservation = new
{
Id = reservationId,
Name = txtName.Text,
Email = txtEmail.Text,
Phone = txtPhone.Text,
ReservationDate = dpDate.Value.Date,
ReservationTime = TimeSpan.Parse(cbTime.SelectedItem.ToString()),
Guests = (int)numGuests.Value,
Message = txtMessage.Text
};
var options = new JsonSerializerOptions
{
DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
};
var json = JsonSerializer.Serialize(reservation, options);
var content = new StringContent(json, Encoding.UTF8, "application/json");
//HttpResponseMessage resp;
//if (isEdit && reservationId.HasValue)
// resp = await http.PutAsync(url + "/" + reservationId, content);
//else
// resp = await http.PostAsync(url, content);
//if (resp.IsSuccessStatusCode)
//{
// MessageBox.Show(isEdit ? "Бронирование обновлено" : "Бронирование добавлено");
// DialogResult = DialogResult.OK;
// Close();
//}
//else
//{
// MessageBox.Show("Ошибка сохранения: " + resp.StatusCode);
//}
HttpResponseMessage resp;
if (isEdit && reservationId.HasValue)
resp = await http.PutAsync(url + "/" + reservationId, content);
else
resp = await http.PostAsync(url, content);
var responseText = await resp.Content.ReadAsStringAsync();
if (resp.IsSuccessStatusCode)
{
MessageBox.Show(isEdit ? "Бронирование обновлено" : "Бронирование добавлено");
DialogResult = DialogResult.OK;
Close();
}
else
{
string message = $"Ошибка сохранения ({(int)resp.StatusCode})";
try
{
// сообщение из JSON { "message": "..." }
var error = JsonSerializer.Deserialize<Dictionary<string, string>>(responseText);
if (error != null && error.ContainsKey("message"))
message += $": {error["message"]}";
else if (!string.IsNullOrWhiteSpace(responseText))
message += $": {responseText}";
}
catch
{
// Если не удалось распарсить JSON — покажем как есть
if (!string.IsNullOrWhiteSpace(responseText))
message += $": {responseText}";
}
MessageBox.Show(message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private class ReservationDto
{
public DateTime ReservationDate { get; set; }
public TimeSpan ReservationTime { get; set; }
}
}
}