first step
This commit is contained in:
parent
f2142b75a9
commit
76e6ec8bc5
13
Hotel/.idea/.idea.Hotel/.idea/.gitignore
vendored
Normal file
13
Hotel/.idea/.idea.Hotel/.idea/.gitignore
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Rider ignored files
|
||||
/modules.xml
|
||||
/contentModel.xml
|
||||
/projectSettingsUpdater.xml
|
||||
/.idea.Hotel.iml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
4
Hotel/.idea/.idea.Hotel/.idea/encodings.xml
Normal file
4
Hotel/.idea/.idea.Hotel/.idea/encodings.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||
</project>
|
10
Hotel/.idea/.idea.Hotel/.idea/indexLayout.xml
Normal file
10
Hotel/.idea/.idea.Hotel/.idea/indexLayout.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UserContentModel">
|
||||
<attachedFolders>
|
||||
<Path>../../PIbd-22_Bazunov_AI_Hotel</Path>
|
||||
</attachedFolders>
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,19 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="CssUnknownProperty" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="myCustomPropertiesEnabled" value="true" />
|
||||
<option name="myIgnoreVendorSpecificProperties" value="false" />
|
||||
<option name="myCustomPropertiesList">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="flex-line-pack" />
|
||||
<item index="1" class="java.lang.String" itemvalue="initial-value" />
|
||||
<item index="2" class="java.lang.String" itemvalue="inherits" />
|
||||
<item index="3" class="java.lang.String" itemvalue="syntax" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
7
Hotel/.idea/.idea.Hotel/.idea/vcs.xml
Normal file
7
Hotel/.idea/.idea.Hotel/.idea/vcs.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
@ -13,7 +13,7 @@ public class CleaningInstrumentsLogic : ICleaningInstrumentsLogic
|
||||
private readonly ICleaningInstrumentsStorage _cleaningInstruments;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public CleaningInstrumentsLogic(ICleaningInstrumentsStorage cleaningInstruments, ILogger logger)
|
||||
public CleaningInstrumentsLogic(ICleaningInstrumentsStorage cleaningInstruments, ILogger<ICleaningInstrumentsLogic> logger)
|
||||
{
|
||||
_cleaningInstruments = cleaningInstruments;
|
||||
_logger = logger;
|
||||
|
@ -71,7 +71,7 @@ public class CleaningLogic : ICleaningLogic
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
if (!withParams)
|
||||
return;
|
||||
if (model.RoomId < 0)
|
||||
if (model.RoomId <= 0)
|
||||
throw new ArgumentException("RoomId must be more then 0");
|
||||
}
|
||||
}
|
@ -65,6 +65,7 @@ public class ReportLogic : IReportLogic
|
||||
|
||||
list.Add(new ReportListCleaningModel
|
||||
{
|
||||
Id = reservation.Id,
|
||||
RoomNumber = room.Id,
|
||||
StartDate = reservation.StartDate,
|
||||
CleaningInstruments = dict
|
||||
@ -104,7 +105,7 @@ public class ReportLogic : IReportLogic
|
||||
dict.Add(item.Key, view);
|
||||
}
|
||||
|
||||
list.Add(new ReportGuestViewModel()
|
||||
list.Add(new ReportGuestViewModel
|
||||
{
|
||||
Name = guest.Name,
|
||||
SecondName = guest.SecondName,
|
||||
@ -125,7 +126,7 @@ public class ReportLogic : IReportLogic
|
||||
_saveToWord.CreateDoc(new WordInfo
|
||||
{
|
||||
FileName = model.FileName,
|
||||
Title = "Cleaning list",
|
||||
Title = "Комплекты для уборки",
|
||||
ListCleaningModels = GetListCleaning()
|
||||
});
|
||||
}
|
||||
@ -135,7 +136,7 @@ public class ReportLogic : IReportLogic
|
||||
_saveToExcel.CreateReport(new ExcelInfo
|
||||
{
|
||||
FileName = model.FileName,
|
||||
Title = "Cleaning list",
|
||||
Title = "Комплекты для уборки",
|
||||
ListCleaningModels = GetListCleaning()
|
||||
});
|
||||
}
|
||||
@ -145,9 +146,10 @@ public class ReportLogic : IReportLogic
|
||||
_saveToPdf.CreateDoc(new PdfInfo
|
||||
{
|
||||
FileName = model.FileName,
|
||||
Title = "Guests with sets of cleanings",
|
||||
Title = "Постояльцы и комплекты уборки номеров",
|
||||
DateFrom = (DateTime)model.From,
|
||||
DateTo = (DateTime)model.To
|
||||
DateTo = (DateTime)model.To,
|
||||
Guest = GetGuests(model)
|
||||
});
|
||||
}
|
||||
}
|
@ -12,8 +12,9 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DocumentFormat.OpenXml" Version="2.20.0" />
|
||||
<PackageReference Include="MailKit" Version="4.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0-preview.2.23128.3" />
|
||||
<PackageReference Include="PDFsharp-MigraDoc" Version="6.0.0-preview-1" />
|
||||
<PackageReference Include="PDFsharp-MigraDoc-GDI" Version="1.50.5147" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
57
Hotel/HotelBusinessLogic/MailWorker/AbstractMailWorker.cs
Normal file
57
Hotel/HotelBusinessLogic/MailWorker/AbstractMailWorker.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using HotelContracts.BindingModels;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace HotelBusinessLogic.MailWorker;
|
||||
|
||||
public abstract class AbstractMailWorker
|
||||
{
|
||||
protected string _mailLogin = string.Empty;
|
||||
protected string _mailPassword = string.Empty;
|
||||
protected string _smtpClientHost = string.Empty;
|
||||
protected int _smtpClientPort;
|
||||
protected string _popHost = string.Empty;
|
||||
protected int _popPort;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
protected AbstractMailWorker(ILogger<AbstractMailWorker> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void MailConfig(MailConfigBindingModel config)
|
||||
{
|
||||
_mailLogin = config.MailLogin;
|
||||
_mailPassword = config.MailPassword;
|
||||
_smtpClientHost = config.SmtpClientHost;
|
||||
_smtpClientPort = config.SmtpClientPort;
|
||||
_popHost = config.PopHost;
|
||||
_popPort = config.PopPort;
|
||||
_logger.LogDebug("Config: {login}, {password}, {clientHost}, {clientPOrt}, {popHost}, {popPort}",
|
||||
_mailLogin, _mailPassword, _smtpClientHost, _smtpClientPort, _popHost, _popPort);
|
||||
}
|
||||
|
||||
public async void MailSendAsync(MailSendInfoBindingModel info)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_mailLogin) ||
|
||||
string.IsNullOrEmpty(_mailPassword))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (string.IsNullOrEmpty(_smtpClientHost) ||
|
||||
_smtpClientPort == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (string.IsNullOrEmpty(info.MailAddress) ||
|
||||
string.IsNullOrEmpty(info.Subject))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogDebug("Send Mail: {To}, {Subject}", info.MailAddress,
|
||||
info.Subject);
|
||||
await SendMailAsync(info);
|
||||
}
|
||||
|
||||
protected abstract Task SendMailAsync(MailSendInfoBindingModel info);
|
||||
}
|
36
Hotel/HotelBusinessLogic/MailWorker/MailKitWorker.cs
Normal file
36
Hotel/HotelBusinessLogic/MailWorker/MailKitWorker.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Net;
|
||||
using System.Net.Mail;
|
||||
using System.Text;
|
||||
using HotelContracts.BindingModels;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace HotelBusinessLogic.MailWorker;
|
||||
|
||||
public class MailKitWorker : AbstractMailWorker
|
||||
{
|
||||
public MailKitWorker(ILogger<MailKitWorker> logger) : base(logger) {}
|
||||
|
||||
protected override async Task SendMailAsync(MailSendInfoBindingModel info)
|
||||
{
|
||||
using var objMailMessage = new MailMessage();
|
||||
using var objSmtpClient = new SmtpClient(_smtpClientHost, _smtpClientPort);
|
||||
objMailMessage.From = new MailAddress(_mailLogin);
|
||||
objMailMessage.To.Add(new MailAddress(info.MailAddress));
|
||||
objMailMessage.Subject = info.Subject;
|
||||
objMailMessage.Attachments.Add(info.AttachmentMail);
|
||||
objMailMessage.SubjectEncoding = Encoding.UTF8;
|
||||
objMailMessage.BodyEncoding = Encoding.UTF8;
|
||||
objSmtpClient.UseDefaultCredentials = false;
|
||||
objSmtpClient.EnableSsl = true;
|
||||
objSmtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
|
||||
objSmtpClient.Credentials = new NetworkCredential(_mailLogin, _mailPassword);
|
||||
try
|
||||
{
|
||||
await Task.Run(() => objSmtpClient.Send(objMailMessage));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
@ -6,66 +6,107 @@ namespace HotelBusinessLogic.OfficePackage;
|
||||
public abstract class AbstractSaveToExcel
|
||||
{
|
||||
public void CreateReport(ExcelInfo info)
|
||||
{
|
||||
CreateExcel(info);
|
||||
{
|
||||
CreateExcel(info);
|
||||
|
||||
InsertCellInWorksheet(new ExcelCellParameters
|
||||
{
|
||||
ColumnName = "A",
|
||||
RowIndex = 1,
|
||||
Text = info.Title,
|
||||
StyleInfo = ExcelStyleInfoType.Title
|
||||
});
|
||||
|
||||
MergeCells(new ExcelMergeParameters
|
||||
{
|
||||
CellFromName = "A1",
|
||||
CellToName = "C1"
|
||||
});
|
||||
|
||||
uint rowIndex = 2;
|
||||
|
||||
foreach (var mc in info.ListCleaningModels)
|
||||
{
|
||||
InsertCellInWorksheet(new ExcelCellParameters
|
||||
{
|
||||
ColumnName = "A",
|
||||
RowIndex = 1,
|
||||
Text = info.Title,
|
||||
RowIndex = rowIndex,
|
||||
Text = "Бронь #" + mc.Id,
|
||||
StyleInfo = ExcelStyleInfoType.Title
|
||||
});
|
||||
|
||||
|
||||
MergeCells(new ExcelMergeParameters
|
||||
{
|
||||
CellFromName = "A1",
|
||||
CellToName = "C1"
|
||||
CellFromName = "A" + rowIndex,
|
||||
CellToName = "C" + rowIndex
|
||||
});
|
||||
|
||||
uint rowIndex = 2;
|
||||
rowIndex++;
|
||||
|
||||
InsertCellInWorksheet(new ExcelCellParameters
|
||||
{
|
||||
ColumnName = "A",
|
||||
RowIndex = rowIndex,
|
||||
Text = "Дата начала бронирования",
|
||||
StyleInfo = ExcelStyleInfoType.Text
|
||||
});
|
||||
|
||||
InsertCellInWorksheet(new ExcelCellParameters
|
||||
{
|
||||
ColumnName = "B",
|
||||
RowIndex = rowIndex,
|
||||
Text = "Номер гостиницы",
|
||||
StyleInfo = ExcelStyleInfoType.TextWithBroder
|
||||
});
|
||||
|
||||
InsertCellInWorksheet(new ExcelCellParameters
|
||||
{
|
||||
ColumnName = "C",
|
||||
RowIndex = rowIndex,
|
||||
Text = "Набор",
|
||||
StyleInfo = ExcelStyleInfoType.TextWithBroder
|
||||
});
|
||||
|
||||
foreach (var mc in info.ListCleaningModels)
|
||||
|
||||
rowIndex++;
|
||||
|
||||
InsertCellInWorksheet(new ExcelCellParameters
|
||||
{
|
||||
ColumnName = "A",
|
||||
RowIndex = rowIndex,
|
||||
Text = mc.StartDate.ToString(),
|
||||
StyleInfo = ExcelStyleInfoType.Text
|
||||
});
|
||||
|
||||
InsertCellInWorksheet(new ExcelCellParameters
|
||||
{
|
||||
ColumnName = "B",
|
||||
RowIndex = rowIndex,
|
||||
Text = mc.RoomNumber.ToString(),
|
||||
StyleInfo = ExcelStyleInfoType.TextWithBroder
|
||||
});
|
||||
|
||||
foreach (var valuePair in mc.CleaningInstruments.Values)
|
||||
{
|
||||
InsertCellInWorksheet(new ExcelCellParameters
|
||||
{
|
||||
ColumnName = "A",
|
||||
ColumnName = "C",
|
||||
RowIndex = rowIndex,
|
||||
Text = mc.StartDate.ToString(),
|
||||
StyleInfo = ExcelStyleInfoType.Text
|
||||
});
|
||||
|
||||
InsertCellInWorksheet(new ExcelCellParameters
|
||||
{
|
||||
ColumnName = "B",
|
||||
RowIndex = rowIndex,
|
||||
Text = mc.RoomNumber.ToString(),
|
||||
Text = valuePair.Type,
|
||||
StyleInfo = ExcelStyleInfoType.TextWithBroder
|
||||
});
|
||||
|
||||
rowIndex++;
|
||||
|
||||
foreach (var valuePair in mc.CleaningInstruments.Values)
|
||||
{
|
||||
InsertCellInWorksheet(new ExcelCellParameters
|
||||
{
|
||||
ColumnName = "C",
|
||||
RowIndex = rowIndex,
|
||||
Text = valuePair.Type,
|
||||
StyleInfo = ExcelStyleInfoType.TextWithBroder
|
||||
});
|
||||
|
||||
rowIndex++;
|
||||
}
|
||||
|
||||
rowIndex++;
|
||||
}
|
||||
|
||||
SaveExcel(info);
|
||||
rowIndex++;
|
||||
}
|
||||
|
||||
protected abstract void CreateExcel(ExcelInfo info);
|
||||
protected abstract void InsertCellInWorksheet(ExcelCellParameters excelParams);
|
||||
protected abstract void MergeCells(ExcelMergeParameters excelParams);
|
||||
protected abstract void SaveExcel(ExcelInfo info);
|
||||
SaveExcel(info);
|
||||
}
|
||||
|
||||
protected abstract void CreateExcel(ExcelInfo info);
|
||||
protected abstract void InsertCellInWorksheet(ExcelCellParameters excelParams);
|
||||
protected abstract void MergeCells(ExcelMergeParameters excelParams);
|
||||
protected abstract void SaveExcel(ExcelInfo info);
|
||||
}
|
@ -6,55 +6,55 @@ namespace HotelBusinessLogic.OfficePackage;
|
||||
public abstract class AbstractSaveToPdf
|
||||
{
|
||||
public void CreateDoc(PdfInfo info)
|
||||
{
|
||||
CreatePdf(info);
|
||||
CreateParagraph(new PdfParagraph
|
||||
{
|
||||
Text = info.Title,
|
||||
Style = "NormalTitle",
|
||||
ParagraphAlignment = PdfParagraphAlignmentType.Center
|
||||
});
|
||||
CreateParagraph(new PdfParagraph
|
||||
{
|
||||
Text = $"С {info.DateFrom.ToShortDateString()} По {info.DateTo.ToShortDateString()}",
|
||||
Style = "Normal",
|
||||
ParagraphAlignment = PdfParagraphAlignmentType.Center
|
||||
});
|
||||
CreateTable(new List<string> { "3cm", "3cm", "3cm", "3cm", "3cm", "10cm" });
|
||||
CreateRow(new PdfRowParameters
|
||||
{
|
||||
Texts = new List<string> { "Фамилия", "Имя", "Отчество", "Заселение", "Выселение", "Набор" },
|
||||
Style = "NormalTitle",
|
||||
ParagraphAlignment = PdfParagraphAlignmentType.Center
|
||||
});
|
||||
foreach (var model in info.Guest)
|
||||
{
|
||||
CreatePdf(info);
|
||||
CreateParagraph(new PdfParagraph
|
||||
{
|
||||
Text = info.Title,
|
||||
Style = "NormalTitle",
|
||||
ParagraphAlignment = PdfParagraphAlignmentType.Center
|
||||
});
|
||||
CreateParagraph(new PdfParagraph
|
||||
{
|
||||
Text = $"From {info.DateFrom.ToShortDateString()} to {info.DateTo.ToShortDateString()}",
|
||||
Style = "Normal",
|
||||
ParagraphAlignment = PdfParagraphAlignmentType.Center
|
||||
});
|
||||
CreateTable(new List<string> { "3cm", "3cm", "3cm", "3cm", "3cm", "10cm" });
|
||||
CreateRow(new PdfRowParameters
|
||||
{
|
||||
Texts = new List<string> { "Second Name", "Name", "Last Name", "Settlement", "Eviction", "Cleaning set" },
|
||||
Style = "NormalTitle",
|
||||
ParagraphAlignment = PdfParagraphAlignmentType.Center
|
||||
});
|
||||
foreach (var model in info.Guest)
|
||||
{
|
||||
CreateRow(new PdfRowParameters
|
||||
{
|
||||
Texts = new List<string>
|
||||
{
|
||||
model.SecondName,
|
||||
model.Name,
|
||||
model.LastName,
|
||||
model.StartDate.ToShortDateString(),
|
||||
model.EndDate.ToShortDateString(),
|
||||
model.CleaningInstruments.Values.Select(x => x.Type).ToString()
|
||||
},
|
||||
Style = "Normal",
|
||||
ParagraphAlignment = PdfParagraphAlignmentType.Left
|
||||
});
|
||||
}
|
||||
CreateParagraph(new PdfParagraph
|
||||
{
|
||||
Text = $"Summary: {info.Guest.Count}\t",
|
||||
Texts = new List<string>
|
||||
{
|
||||
model.SecondName,
|
||||
model.Name,
|
||||
model.LastName,
|
||||
model.StartDate.ToShortDateString(),
|
||||
model.EndDate.ToShortDateString(),
|
||||
string.Join(",", model.CleaningInstruments.Values.Select(x => x.Type))
|
||||
},
|
||||
Style = "Normal",
|
||||
ParagraphAlignment = PdfParagraphAlignmentType.Right
|
||||
ParagraphAlignment = PdfParagraphAlignmentType.Left
|
||||
});
|
||||
SavePdf(info);
|
||||
}
|
||||
protected abstract void CreatePdf(PdfInfo info);
|
||||
protected abstract void CreateParagraph(PdfParagraph paragraph);
|
||||
protected abstract void CreateTable(List<string> columns);
|
||||
protected abstract void CreateRow(PdfRowParameters rowParameters);
|
||||
protected abstract void SavePdf(PdfInfo info);
|
||||
CreateParagraph(new PdfParagraph
|
||||
{
|
||||
Text = $"Summary: {info.Guest.Count}\t",
|
||||
Style = "Normal",
|
||||
ParagraphAlignment = PdfParagraphAlignmentType.Right
|
||||
});
|
||||
SavePdf(info);
|
||||
}
|
||||
protected abstract void CreatePdf(PdfInfo info);
|
||||
protected abstract void CreateParagraph(PdfParagraph paragraph);
|
||||
protected abstract void CreateTable(List<string> columns);
|
||||
protected abstract void CreateRow(PdfRowParameters rowParameters);
|
||||
protected abstract void SavePdf(PdfInfo info);
|
||||
}
|
@ -6,43 +6,50 @@ namespace HotelBusinessLogic.OfficePackage;
|
||||
public abstract class AbstractSaveToWord
|
||||
{
|
||||
public void CreateDoc(WordInfo info)
|
||||
{
|
||||
CreateWord(info);
|
||||
CreateParagraph(new WordParagraph
|
||||
{
|
||||
CreateWord(info);
|
||||
Texts = new List<(string, WordTextProperties)> { (info.Title, new WordTextProperties { Bold = true, Size = "24", }) },
|
||||
TextProperties = new WordTextProperties
|
||||
{
|
||||
Size = "24",
|
||||
JustificationType = WordJustificationType.Center
|
||||
}
|
||||
});
|
||||
|
||||
foreach (var mc in info.ListCleaningModels)
|
||||
{
|
||||
var set = string.Join(", ", mc.CleaningInstruments
|
||||
.Values
|
||||
.Select(x => x.Type));
|
||||
|
||||
CreateParagraph(new WordParagraph
|
||||
{
|
||||
Texts = new List<(string, WordTextProperties)> { (info.Title, new WordTextProperties { Bold = true, Size = "24", }) },
|
||||
Texts = new List<(string, WordTextProperties)> { ("Бронь " + mc.Id, new WordTextProperties { Bold = true, Size = "24", }) },
|
||||
TextProperties = new WordTextProperties
|
||||
{
|
||||
Size = "24",
|
||||
JustificationType = WordJustificationType.Center
|
||||
JustificationType = WordJustificationType.Both
|
||||
}
|
||||
});
|
||||
|
||||
foreach (var mc in info.ListCleaningModels)
|
||||
CreateParagraph(new WordParagraph
|
||||
{
|
||||
string? set = mc.CleaningInstruments
|
||||
.Values
|
||||
.Select(x => x.Type)
|
||||
.ToList()
|
||||
.ToString();
|
||||
|
||||
CreateParagraph(new WordParagraph
|
||||
Texts = new List<(string, WordTextProperties)>
|
||||
{(
|
||||
mc.StartDate.ToShortDateString() + " - " + mc.RoomNumber + " - " + set, new WordTextProperties { Size = "20", Bold=false}
|
||||
)},
|
||||
TextProperties = new WordTextProperties
|
||||
{
|
||||
Texts = new List<(string, WordTextProperties)>
|
||||
{(
|
||||
mc.StartDate.ToShortDateString() + " - " + mc.RoomNumber + " - " + set, new WordTextProperties { Size = "24", Bold=true}
|
||||
)},
|
||||
TextProperties = new WordTextProperties
|
||||
{
|
||||
Size = "24",
|
||||
JustificationType = WordJustificationType.Both
|
||||
}
|
||||
});
|
||||
}
|
||||
SaveWord(info);
|
||||
Size = "24",
|
||||
JustificationType = WordJustificationType.Both
|
||||
}
|
||||
});
|
||||
}
|
||||
SaveWord(info);
|
||||
}
|
||||
|
||||
protected abstract void CreateWord(WordInfo info);
|
||||
protected abstract void CreateParagraph(WordParagraph? paragraph);
|
||||
protected abstract void SaveWord(WordInfo info);
|
||||
protected abstract void CreateWord(WordInfo info);
|
||||
protected abstract void CreateParagraph(WordParagraph? paragraph);
|
||||
protected abstract void SaveWord(WordInfo info);
|
||||
}
|
@ -30,6 +30,7 @@ public class SaveToPdf : AbstractSaveToPdf
|
||||
style.Font.Size = 14;
|
||||
}
|
||||
|
||||
document.DefaultPageSetup.Orientation = Orientation.Landscape;
|
||||
style = document.Styles.AddStyle("NormalTitle", "Normal");
|
||||
style.Font.Bold = true;
|
||||
}
|
||||
|
11
Hotel/HotelContracts/BindingModels/MailConfigBindingModel.cs
Normal file
11
Hotel/HotelContracts/BindingModels/MailConfigBindingModel.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace HotelContracts.BindingModels;
|
||||
|
||||
public class MailConfigBindingModel
|
||||
{
|
||||
public string MailLogin { get; set; } = string.Empty;
|
||||
public string MailPassword { get; set; } = string.Empty;
|
||||
public string SmtpClientHost { get; set; } = string.Empty;
|
||||
public int SmtpClientPort { get; set; }
|
||||
public string PopHost { get; set; } = string.Empty;
|
||||
public int PopPort { get; set; }
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
using System.Net.Mail;
|
||||
|
||||
namespace HotelContracts.BindingModels;
|
||||
|
||||
public class MailSendInfoBindingModel
|
||||
{
|
||||
public string MailAddress { get; set; } = string.Empty;
|
||||
public string Subject { get; set; } = string.Empty;
|
||||
public Attachment AttachmentMail { get; set; }
|
||||
}
|
@ -7,4 +7,5 @@ public class RoomBindingModel : IRoomModel
|
||||
public int Id { get; set; }
|
||||
public string Type { get; set; }
|
||||
public double Cost { get; set; }
|
||||
public bool IsReserved { get; set; }
|
||||
}
|
@ -5,4 +5,5 @@ public class RoomSearchModel
|
||||
public int? Id { get; set; }
|
||||
public double? Cost { get; set; }
|
||||
public string? Type { get; set; }
|
||||
public bool? IsReserved { get; set; }
|
||||
}
|
@ -8,4 +8,5 @@ public class CleaningViewModel : ICleaningModel
|
||||
public DateTime Date { get; set; }
|
||||
public int RoomId { get; set; }
|
||||
public Dictionary<int, ICleaningInstrumentsModel> CleaningInstruments { get; set; }
|
||||
public RoomViewModel Room { get; set; }
|
||||
}
|
@ -8,4 +8,6 @@ public class GuestViewModel : IGuestModel
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string SecondName { get; set; } = string.Empty;
|
||||
public string LastName { get; set; } = string.Empty;
|
||||
|
||||
public string Fio => SecondName + " " + Name + " " + LastName;
|
||||
}
|
@ -10,4 +10,6 @@ public class MaitreViewModel : IMaitreModel
|
||||
public string LastName { get; set; } = string.Empty;
|
||||
public string Login { get; set; } = string.Empty;
|
||||
public string Password { get; set; } = string.Empty;
|
||||
|
||||
public string Fio => SecondName + " " + Name + " " + LastName;
|
||||
}
|
@ -13,4 +13,11 @@ public class ReservationViewModel : IReservationModel
|
||||
public int GuestId { get; set; }
|
||||
public int MaitreId { get; set; }
|
||||
public Dictionary<int, IRoomModel> ReservationsRooms { get; set; }
|
||||
public GuestViewModel Guest { get; set; }
|
||||
|
||||
public double GetCost()
|
||||
{
|
||||
var days = EndDate - StartDate;
|
||||
return ReservationsRooms.Sum(room => room.Value.Cost * days.Days);
|
||||
}
|
||||
}
|
@ -6,6 +6,22 @@ namespace HotelContracts.ViewModels;
|
||||
public class RoomViewModel : IRoomModel
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Type { get; set; } = string.Empty;
|
||||
public string Type { get; set; }
|
||||
public double Cost { get; set; }
|
||||
public bool IsReserved { get; set; }
|
||||
public Dictionary<int, IReservationModel> Reservation { get; set; }
|
||||
|
||||
public string GetTypeRoom()
|
||||
{
|
||||
return Type switch
|
||||
{
|
||||
"standard" => "Стандартный",
|
||||
"superior" => "Улучшенный",
|
||||
"bedroom" => "Со спальной комнатой",
|
||||
"apartment" => "Апартаменты/квартира",
|
||||
"studio" => "Студия",
|
||||
"suite" => "Люкс",
|
||||
_ => ""
|
||||
};
|
||||
}
|
||||
}
|
@ -20,4 +20,8 @@
|
||||
<ProjectReference Include="..\HotelDataModels\HotelDataModels.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Migrations" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -30,9 +30,14 @@ public class CleaningStorage : ICleaningStorage
|
||||
|
||||
public CleaningViewModel? GetElement(CleaningSearchModel model)
|
||||
{
|
||||
if (!model.Id.HasValue) return null;
|
||||
using var context = new HotelDataBase();
|
||||
return context.Cleanings.FirstOrDefault(x => x.Id == model.Id)?.GetView;
|
||||
if (model.RoomId.HasValue)
|
||||
{
|
||||
return context.Cleanings.FirstOrDefault(x => x.RoomId == model.RoomId)?.GetView;
|
||||
}
|
||||
return !model.Id.HasValue ?
|
||||
null :
|
||||
context.Cleanings.FirstOrDefault(x => x.Id == model.Id)?.GetView;
|
||||
}
|
||||
|
||||
public CleaningViewModel? Insert(CleaningBindingModel model)
|
||||
|
@ -32,9 +32,10 @@ public class MaitreStorage : IMaitreStorage
|
||||
|
||||
public MaitreViewModel? GetElement(MaitreSearchModel model)
|
||||
{
|
||||
if (!model.Id.HasValue) return null;
|
||||
using var context = new HotelDataBase();
|
||||
return context.Maitres.FirstOrDefault(x => x.Id == model.Id)?.GetViewModel;
|
||||
return string.IsNullOrEmpty(model.Login) ?
|
||||
context.Maitres.FirstOrDefault(x => x.Id == model.Id)?.GetViewModel :
|
||||
context.Maitres.FirstOrDefault(x => x.Login == model.Login)?.GetViewModel;
|
||||
}
|
||||
|
||||
public MaitreViewModel? Insert(MaitreBindingModel model)
|
||||
|
@ -19,9 +19,16 @@ public class ReservationStorage : IReservationStorage
|
||||
|
||||
public List<ReservationViewModel> GetFilteredList(ReservationSearchModel model)
|
||||
{
|
||||
if (!model.From.HasValue || !model.To.HasValue)
|
||||
return new List<ReservationViewModel>();
|
||||
using var context = new HotelDataBase();
|
||||
if (model.GuestId.HasValue)
|
||||
{
|
||||
return context.Reservations
|
||||
.Where(x => x.GuestId == model.GuestId)
|
||||
.Select(x => x.GetView)
|
||||
.ToList();
|
||||
}
|
||||
if (!model.From.HasValue || !model.To.HasValue || !model.GuestId.HasValue)
|
||||
return new List<ReservationViewModel>();
|
||||
return context.Reservations
|
||||
.Where(x => x.StartDate >= model.From && x.StartDate <= model.To)
|
||||
.Select(x => x.GetView)
|
||||
@ -35,13 +42,36 @@ public class ReservationStorage : IReservationStorage
|
||||
return context.Reservations.FirstOrDefault(x => x.Id == model.Id)?.GetView;
|
||||
}
|
||||
|
||||
public void SwitchRoomReserve(Reservation reservation, HotelDataBase context, bool state = true)
|
||||
{
|
||||
if (reservation.Rooms.Count > 0)
|
||||
{
|
||||
foreach (var roomItem in reservation.Rooms
|
||||
.Select(x => context.Rooms.FirstOrDefault(y => y.Id == x.RoomId)))
|
||||
{
|
||||
if (roomItem is null) return;
|
||||
roomItem.IsReserved = state;
|
||||
context.Rooms.Update(roomItem);
|
||||
}
|
||||
return;
|
||||
}
|
||||
foreach (var roomItem in reservation.ReservationsRooms
|
||||
.Select(x => context.Rooms.FirstOrDefault(y => y.Id == x.Key)))
|
||||
{
|
||||
if (roomItem is null) return;
|
||||
roomItem.IsReserved = state;
|
||||
context.Rooms.Update(roomItem);
|
||||
}
|
||||
}
|
||||
|
||||
public ReservationViewModel? Insert(ReservationBindingModel model)
|
||||
{
|
||||
using var context = new HotelDataBase();
|
||||
var item = Reservation.Create(context, model);
|
||||
if (item == null) return null;
|
||||
|
||||
|
||||
context.Reservations.Add(item);
|
||||
SwitchRoomReserve(item, context);
|
||||
context.SaveChanges();
|
||||
|
||||
return item.GetView;
|
||||
@ -64,6 +94,7 @@ public class ReservationStorage : IReservationStorage
|
||||
var item = context.Reservations.FirstOrDefault(x => x.Id == model.Id);
|
||||
if (item == null) return null;
|
||||
context.Reservations.Remove(item);
|
||||
SwitchRoomReserve(item, context, false);
|
||||
context.SaveChanges();
|
||||
return item.GetView;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ using HotelContracts.SearchModels;
|
||||
using HotelContracts.StoragesContracts;
|
||||
using HotelContracts.ViewModels;
|
||||
using HotelDatabaseImplement.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace HotelDatabaseImplement.Implements;
|
||||
|
||||
@ -18,12 +19,15 @@ public class RoomStorage : IRoomStorage
|
||||
|
||||
public List<RoomViewModel> GetFilteredList(RoomSearchModel model)
|
||||
{
|
||||
if (string.IsNullOrEmpty(model.Type))
|
||||
{
|
||||
return new List<RoomViewModel>();
|
||||
}
|
||||
|
||||
using var context = new HotelDataBase();
|
||||
if (model.IsReserved.HasValue)
|
||||
{
|
||||
return context.Rooms
|
||||
.Where(x => x.IsReserved == model.IsReserved)
|
||||
.Select(x => x.GetView)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
if (model.Cost.HasValue)
|
||||
{
|
||||
return context.Rooms
|
||||
|
@ -12,8 +12,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
namespace HotelDatabaseImplement.Migrations
|
||||
{
|
||||
[DbContext(typeof(HotelDataBase))]
|
||||
[Migration("20230407095141_init")]
|
||||
partial class init
|
||||
[Migration("20230518201459_1")]
|
||||
partial class _1
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
@ -181,14 +181,11 @@ namespace HotelDatabaseImplement.Migrations
|
||||
b.Property<int>("RoomId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("RoomId1")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoomId");
|
||||
b.HasIndex("ReservationId");
|
||||
|
||||
b.HasIndex("RoomId1");
|
||||
b.HasIndex("RoomId");
|
||||
|
||||
b.ToTable("ReservationRooms");
|
||||
});
|
||||
@ -204,8 +201,8 @@ namespace HotelDatabaseImplement.Migrations
|
||||
b.Property<double>("Cost")
|
||||
.HasColumnType("float");
|
||||
|
||||
b.Property<int>("ReservationId")
|
||||
.HasColumnType("int");
|
||||
b.Property<bool>("IsReserved")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
@ -213,8 +210,6 @@ namespace HotelDatabaseImplement.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ReservationId");
|
||||
|
||||
b.ToTable("Rooms");
|
||||
});
|
||||
|
||||
@ -241,28 +236,19 @@ namespace HotelDatabaseImplement.Migrations
|
||||
{
|
||||
b.HasOne("HotelDatabaseImplement.Models.Reservation", "Reservation")
|
||||
.WithMany("Rooms")
|
||||
.HasForeignKey("RoomId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("HotelDatabaseImplement.Models.Room", "Room")
|
||||
.WithMany()
|
||||
.HasForeignKey("RoomId1");
|
||||
|
||||
b.Navigation("Reservation");
|
||||
|
||||
b.Navigation("Room");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("HotelDatabaseImplement.Models.Room", b =>
|
||||
{
|
||||
b.HasOne("HotelDatabaseImplement.Models.Reservation", "Reservation")
|
||||
.WithMany()
|
||||
.HasForeignKey("ReservationId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("HotelDatabaseImplement.Models.Room", "Room")
|
||||
.WithMany("Reservation")
|
||||
.HasForeignKey("RoomId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Reservation");
|
||||
|
||||
b.Navigation("Room");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("HotelDatabaseImplement.Models.Cleaning", b =>
|
||||
@ -274,6 +260,11 @@ namespace HotelDatabaseImplement.Migrations
|
||||
{
|
||||
b.Navigation("Rooms");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("HotelDatabaseImplement.Models.Room", b =>
|
||||
{
|
||||
b.Navigation("Reservation");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
|
||||
namespace HotelDatabaseImplement.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class init : Migration
|
||||
public partial class _1 : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
@ -86,6 +86,21 @@ namespace HotelDatabaseImplement.Migrations
|
||||
table.PrimaryKey("PK_Reservations", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Rooms",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("SqlServer:Identity", "1, 1"),
|
||||
Type = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
Cost = table.Column<double>(type: "float", nullable: false),
|
||||
IsReserved = table.Column<bool>(type: "bit", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Rooms", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "CleaningInstrument",
|
||||
columns: table => new
|
||||
@ -112,27 +127,6 @@ namespace HotelDatabaseImplement.Migrations
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Rooms",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("SqlServer:Identity", "1, 1"),
|
||||
Type = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
Cost = table.Column<double>(type: "float", nullable: false),
|
||||
ReservationId = table.Column<int>(type: "int", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Rooms", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Rooms_Reservations_ReservationId",
|
||||
column: x => x.ReservationId,
|
||||
principalTable: "Reservations",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ReservationRooms",
|
||||
columns: table => new
|
||||
@ -140,23 +134,23 @@ namespace HotelDatabaseImplement.Migrations
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("SqlServer:Identity", "1, 1"),
|
||||
ReservationId = table.Column<int>(type: "int", nullable: false),
|
||||
RoomId = table.Column<int>(type: "int", nullable: false),
|
||||
RoomId1 = table.Column<int>(type: "int", nullable: true)
|
||||
RoomId = table.Column<int>(type: "int", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ReservationRooms", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_ReservationRooms_Reservations_RoomId",
|
||||
column: x => x.RoomId,
|
||||
name: "FK_ReservationRooms_Reservations_ReservationId",
|
||||
column: x => x.ReservationId,
|
||||
principalTable: "Reservations",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_ReservationRooms_Rooms_RoomId1",
|
||||
column: x => x.RoomId1,
|
||||
name: "FK_ReservationRooms_Rooms_RoomId",
|
||||
column: x => x.RoomId,
|
||||
principalTable: "Rooms",
|
||||
principalColumn: "Id");
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
@ -169,20 +163,15 @@ namespace HotelDatabaseImplement.Migrations
|
||||
table: "CleaningInstrument",
|
||||
column: "CleaningInstrumentsId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ReservationRooms_ReservationId",
|
||||
table: "ReservationRooms",
|
||||
column: "ReservationId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ReservationRooms_RoomId",
|
||||
table: "ReservationRooms",
|
||||
column: "RoomId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ReservationRooms_RoomId1",
|
||||
table: "ReservationRooms",
|
||||
column: "RoomId1");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Rooms_ReservationId",
|
||||
table: "Rooms",
|
||||
column: "ReservationId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -207,10 +196,10 @@ namespace HotelDatabaseImplement.Migrations
|
||||
name: "Cleanings");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Rooms");
|
||||
name: "Reservations");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Reservations");
|
||||
name: "Rooms");
|
||||
}
|
||||
}
|
||||
}
|
@ -178,14 +178,11 @@ namespace HotelDatabaseImplement.Migrations
|
||||
b.Property<int>("RoomId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("RoomId1")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoomId");
|
||||
b.HasIndex("ReservationId");
|
||||
|
||||
b.HasIndex("RoomId1");
|
||||
b.HasIndex("RoomId");
|
||||
|
||||
b.ToTable("ReservationRooms");
|
||||
});
|
||||
@ -201,8 +198,8 @@ namespace HotelDatabaseImplement.Migrations
|
||||
b.Property<double>("Cost")
|
||||
.HasColumnType("float");
|
||||
|
||||
b.Property<int>("ReservationId")
|
||||
.HasColumnType("int");
|
||||
b.Property<bool>("IsReserved")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
@ -210,8 +207,6 @@ namespace HotelDatabaseImplement.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ReservationId");
|
||||
|
||||
b.ToTable("Rooms");
|
||||
});
|
||||
|
||||
@ -238,28 +233,19 @@ namespace HotelDatabaseImplement.Migrations
|
||||
{
|
||||
b.HasOne("HotelDatabaseImplement.Models.Reservation", "Reservation")
|
||||
.WithMany("Rooms")
|
||||
.HasForeignKey("RoomId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("HotelDatabaseImplement.Models.Room", "Room")
|
||||
.WithMany()
|
||||
.HasForeignKey("RoomId1");
|
||||
|
||||
b.Navigation("Reservation");
|
||||
|
||||
b.Navigation("Room");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("HotelDatabaseImplement.Models.Room", b =>
|
||||
{
|
||||
b.HasOne("HotelDatabaseImplement.Models.Reservation", "Reservation")
|
||||
.WithMany()
|
||||
.HasForeignKey("ReservationId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("HotelDatabaseImplement.Models.Room", "Room")
|
||||
.WithMany("Reservation")
|
||||
.HasForeignKey("RoomId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Reservation");
|
||||
|
||||
b.Navigation("Room");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("HotelDatabaseImplement.Models.Cleaning", b =>
|
||||
@ -271,6 +257,11 @@ namespace HotelDatabaseImplement.Migrations
|
||||
{
|
||||
b.Navigation("Rooms");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("HotelDatabaseImplement.Models.Room", b =>
|
||||
{
|
||||
b.Navigation("Reservation");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
|
@ -18,11 +18,12 @@ public class Cleaning : ICleaningModel
|
||||
public Dictionary<int, ICleaningInstrumentsModel> CleaningInstruments {
|
||||
get
|
||||
{
|
||||
_cleaningInstruments ??= CleaningInstrument
|
||||
.ToDictionary(
|
||||
x => x.CleaningInstrumentsId,
|
||||
x => x.CleaningInstruments as ICleaningInstrumentsModel
|
||||
);
|
||||
using var database = new HotelDataBase();
|
||||
_cleaningInstruments ??= database.CleaningInstrument
|
||||
.Where(x => x.CleaningId == Id)
|
||||
.ToDictionary(x => x.CleaningInstrumentsId,
|
||||
y => database.CleaningInstruments.FirstOrDefault(k => k.Id == y.CleaningInstrumentsId) as
|
||||
ICleaningInstrumentsModel);
|
||||
return _cleaningInstruments;
|
||||
}
|
||||
}
|
||||
@ -33,6 +34,7 @@ public class Cleaning : ICleaningModel
|
||||
{
|
||||
Id = model.Id,
|
||||
Date = model.Date,
|
||||
RoomId = model.RoomId,
|
||||
CleaningInstrument = model.CleaningInstruments.Select(
|
||||
x => new CleaningInstrument
|
||||
{
|
||||
@ -78,10 +80,18 @@ public class Cleaning : ICleaningModel
|
||||
_cleaningInstruments = null;
|
||||
}
|
||||
|
||||
public CleaningViewModel GetView => new CleaningViewModel
|
||||
public CleaningViewModel GetView
|
||||
{
|
||||
Id = Id,
|
||||
Date = Date,
|
||||
CleaningInstruments = CleaningInstruments
|
||||
};
|
||||
get
|
||||
{
|
||||
using var context = new HotelDataBase();
|
||||
return new CleaningViewModel
|
||||
{
|
||||
Id = Id,
|
||||
Date = Date,
|
||||
CleaningInstruments = CleaningInstruments,
|
||||
Room = context.Rooms.FirstOrDefault(x => x.Id == RoomId).GetView
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ public class Reservation : IReservationModel
|
||||
public int GuestId { get; set; }
|
||||
public int MaitreId { get; set; }
|
||||
|
||||
[ForeignKey("RoomId")]
|
||||
[ForeignKey("ReservationId")]
|
||||
public virtual List<ReservationRoom> Rooms { get; set; } = new();
|
||||
|
||||
private Dictionary<int, IRoomModel>? _reservationsRooms = null;
|
||||
@ -21,8 +21,11 @@ public class Reservation : IReservationModel
|
||||
{
|
||||
get
|
||||
{
|
||||
_reservationsRooms ??= Rooms
|
||||
.ToDictionary(record => record.RoomId, room => room.Room as IRoomModel);
|
||||
using var database = new HotelDataBase();
|
||||
_reservationsRooms ??= database.ReservationRooms
|
||||
.Where(x => x.ReservationId == Id)
|
||||
.ToDictionary(t => t.RoomId,
|
||||
y => database.Rooms.FirstOrDefault(k => k.Id == y.RoomId)! as IRoomModel);
|
||||
return _reservationsRooms;
|
||||
}
|
||||
}
|
||||
@ -38,6 +41,7 @@ public class Reservation : IReservationModel
|
||||
MaitreId = model.MaitreId,
|
||||
Rooms = model.ReservationsRooms.Select(x => new ReservationRoom
|
||||
{
|
||||
RoomId = x.Key,
|
||||
Room = dataBase.Rooms.First(y => y.Id == x.Key)
|
||||
}).ToList()
|
||||
};
|
||||
@ -68,9 +72,11 @@ public class Reservation : IReservationModel
|
||||
var reservation = dataBase.Reservations.First(x => x.Id == Id);
|
||||
foreach (var reservationRoom in model.ReservationsRooms)
|
||||
{
|
||||
var room = dataBase.Rooms.First(x => x.Id == reservationRoom.Key);
|
||||
room.IsReserved = true;
|
||||
dataBase.ReservationRooms.Add(new ReservationRoom
|
||||
{
|
||||
Room = dataBase.Rooms.First(x => x.Id == reservationRoom.Key),
|
||||
Room = room,
|
||||
Reservation = reservation
|
||||
});
|
||||
dataBase.SaveChanges();
|
||||
@ -79,13 +85,21 @@ public class Reservation : IReservationModel
|
||||
_reservationsRooms = null;
|
||||
}
|
||||
|
||||
public ReservationViewModel GetView => new ReservationViewModel
|
||||
public ReservationViewModel GetView
|
||||
{
|
||||
Id = Id,
|
||||
StartDate = StartDate,
|
||||
EndDate = EndDate,
|
||||
GuestId = GuestId,
|
||||
MaitreId = MaitreId,
|
||||
ReservationsRooms = ReservationsRooms
|
||||
};
|
||||
get
|
||||
{
|
||||
using var context = new HotelDataBase();
|
||||
return new()
|
||||
{
|
||||
Id = Id,
|
||||
StartDate = StartDate,
|
||||
EndDate = EndDate,
|
||||
GuestId = GuestId,
|
||||
MaitreId = MaitreId,
|
||||
ReservationsRooms = ReservationsRooms,
|
||||
Guest = context.Guests.FirstOrDefault(x => x.Id == GuestId)?.GetView
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using HotelContracts.BindingModels;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using HotelContracts.BindingModels;
|
||||
using HotelContracts.ViewModels;
|
||||
using HotelDataModels.Models;
|
||||
|
||||
@ -7,10 +8,24 @@ namespace HotelDatabaseImplement.Models;
|
||||
public class Room : IRoomModel
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Type { get; set; } = string.Empty;
|
||||
public double Cost { get; set; }
|
||||
|
||||
public virtual Reservation Reservation { get; set; } = new();
|
||||
public bool IsReserved { get; set; }
|
||||
|
||||
[ForeignKey("RoomId")]
|
||||
public virtual List<ReservationRoom> Reservation { get; set; } = new();
|
||||
|
||||
private Dictionary<int, IReservationModel>? _reservationsRooms = null;
|
||||
public Dictionary<int, IReservationModel> ReservationsRooms
|
||||
{
|
||||
get
|
||||
{
|
||||
_reservationsRooms ??= Reservation
|
||||
.ToDictionary(record => record.ReservationId,
|
||||
room => room.Reservation as IReservationModel);
|
||||
return _reservationsRooms;
|
||||
}
|
||||
}
|
||||
|
||||
public static Room? Create(RoomBindingModel? model)
|
||||
{
|
||||
@ -38,12 +53,20 @@ public class Room : IRoomModel
|
||||
if (model == null) return;
|
||||
Type = model.Type;
|
||||
Cost = model.Cost;
|
||||
IsReserved = model.IsReserved;
|
||||
}
|
||||
|
||||
public void CheckReservations()
|
||||
{
|
||||
IsReserved = ReservationsRooms.Any(x => x.Value.EndDate > DateTime.Now);
|
||||
}
|
||||
|
||||
public RoomViewModel GetView => new RoomViewModel
|
||||
{
|
||||
Id = Id,
|
||||
Type = Type,
|
||||
Cost = Cost
|
||||
Cost = Cost,
|
||||
Reservation = ReservationsRooms,
|
||||
IsReserved = IsReserved
|
||||
};
|
||||
}
|
123
Hotel/HotelView/Api.cs
Normal file
123
Hotel/HotelView/Api.cs
Normal file
@ -0,0 +1,123 @@
|
||||
using System.Net.Mail;
|
||||
using HotelBusinessLogic.MailWorker;
|
||||
using HotelContracts.BindingModels;
|
||||
using HotelContracts.BusinessLogicsContracts;
|
||||
using HotelContracts.SearchModels;
|
||||
using HotelContracts.StoragesContracts;
|
||||
using HotelContracts.ViewModels;
|
||||
|
||||
namespace HotelView;
|
||||
|
||||
public class Api
|
||||
{
|
||||
private readonly IMaitreLogic _maitreLogic;
|
||||
private readonly AbstractMailWorker _mailWorker;
|
||||
private readonly IReportLogic _reportLogic;
|
||||
public MaitreViewModel? Maitre { get; private set; }
|
||||
|
||||
public Api(IMaitreLogic maitreLogic,
|
||||
IRoomLogic roomLogic,
|
||||
IGuestLogic guestLogic,
|
||||
IReservationLogic reservationLogic,
|
||||
ICleaningInstrumentsLogic getCleaningInstrumentsLogic,
|
||||
ICleaningLogic getCleaningLogic,
|
||||
AbstractMailWorker mailWorker,
|
||||
IReportLogic reportLogic)
|
||||
{
|
||||
_maitreLogic = maitreLogic;
|
||||
GetRoomLogic = roomLogic;
|
||||
GetGuestLogic = guestLogic;
|
||||
GetReservationLogic = reservationLogic;
|
||||
GetCleaningInstrumentsLogic = getCleaningInstrumentsLogic;
|
||||
GetCleaningLogic = getCleaningLogic;
|
||||
_mailWorker = mailWorker;
|
||||
_reportLogic = reportLogic;
|
||||
}
|
||||
|
||||
public IRoomLogic GetRoomLogic { get; }
|
||||
public IGuestLogic GetGuestLogic { get; }
|
||||
public IReservationLogic GetReservationLogic { get; }
|
||||
public ICleaningInstrumentsLogic GetCleaningInstrumentsLogic { get; }
|
||||
public ICleaningLogic GetCleaningLogic { get; }
|
||||
|
||||
public void Auth(string email, string password)
|
||||
{
|
||||
var maitreViewModel = _maitreLogic.ReadElement(new MaitreSearchModel
|
||||
{
|
||||
Login = email
|
||||
});
|
||||
if (maitreViewModel is null) return;
|
||||
if (maitreViewModel.Password.Equals(password))
|
||||
{
|
||||
Maitre = maitreViewModel;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Register(string login,
|
||||
string password,
|
||||
string name,
|
||||
string secondName,
|
||||
string lastName)
|
||||
{
|
||||
return _maitreLogic.Create(new MaitreBindingModel
|
||||
{
|
||||
Login = login,
|
||||
Password = password,
|
||||
Name = name,
|
||||
SecondName = secondName,
|
||||
LastName = lastName
|
||||
});
|
||||
}
|
||||
|
||||
private string GenerateFileName(string ext = "docx") =>
|
||||
"C:/Users/andre/source/repos/PIbd-22_Bazunov_AI_Hotel/Hotel/HotelView/TempDirectoryForReports/" +
|
||||
Maitre.Fio.Replace(" ", "_") + "_" +
|
||||
DateTime.Now.ToShortDateString() + "." + ext;
|
||||
|
||||
public void SendReportWord()
|
||||
{
|
||||
var fileName = GenerateFileName();
|
||||
_reportLogic.SaveListCleaningToWordFile(new ReportBindingModel
|
||||
{
|
||||
FileName = fileName
|
||||
});
|
||||
_mailWorker.MailSendAsync(new MailSendInfoBindingModel
|
||||
{
|
||||
MailAddress = Maitre.Login,
|
||||
Subject = "Список составляющих комплектов для подготовки номеров",
|
||||
AttachmentMail = new Attachment(fileName)
|
||||
});
|
||||
}
|
||||
|
||||
public void SendReportExcel()
|
||||
{
|
||||
var filename = GenerateFileName("xlsx");
|
||||
_reportLogic.SaveListCleaningToExcelFile(new ReportBindingModel
|
||||
{
|
||||
FileName = filename
|
||||
});
|
||||
_mailWorker.MailSendAsync(new MailSendInfoBindingModel
|
||||
{
|
||||
MailAddress = Maitre.Login,
|
||||
Subject = "Список составляющих комплектов для подготовки номеров",
|
||||
AttachmentMail = new Attachment(filename)
|
||||
});
|
||||
}
|
||||
|
||||
public void SendReportPdf(DateTime from, DateTime to)
|
||||
{
|
||||
var filename = GenerateFileName("pdf");
|
||||
_reportLogic.SaveGuestsToPdfFile(new ReportBindingModel
|
||||
{
|
||||
FileName = filename,
|
||||
To = to,
|
||||
From = from
|
||||
});
|
||||
_mailWorker.MailSendAsync(new MailSendInfoBindingModel
|
||||
{
|
||||
MailAddress = Maitre.Login,
|
||||
Subject = "Список гостей с " + from.ToShortDateString() + " по " + to.ToShortDateString(),
|
||||
AttachmentMail = new Attachment(filename)
|
||||
});
|
||||
}
|
||||
}
|
@ -1,32 +1,347 @@
|
||||
using HotelView.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using HotelContracts.BindingModels;
|
||||
using HotelContracts.SearchModels;
|
||||
using HotelContracts.ViewModels;
|
||||
using HotelDataModels.Models;
|
||||
using HotelView.Utils;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||
|
||||
namespace HotelView.Controllers
|
||||
namespace HotelView.Controllers;
|
||||
|
||||
public class HomeController : Controller
|
||||
{
|
||||
public class HomeController : Controller
|
||||
private readonly Api _api;
|
||||
|
||||
public HomeController(Api api)
|
||||
{
|
||||
private readonly ILogger<HomeController> _logger;
|
||||
_api = api;
|
||||
}
|
||||
|
||||
public HomeController(ILogger<HomeController> logger)
|
||||
public IActionResult Index()
|
||||
{
|
||||
if (_api.Maitre is null)
|
||||
{
|
||||
_logger = logger;
|
||||
return Redirect("~/Home/Login");
|
||||
}
|
||||
|
||||
public IActionResult Index()
|
||||
var rooms = _api.GetRoomLogic.ReadList(null);
|
||||
|
||||
ViewBag.Maitre = _api.Maitre;
|
||||
|
||||
ViewBag.RoomIsReserved = Math.Round((double)rooms.Count(x => x.IsReserved) / rooms.Count * 100);
|
||||
ViewBag.RoomIsReservedCount = rooms.Count(x => x.IsReserved);
|
||||
ViewBag.RoomAll = rooms.Count;
|
||||
|
||||
var reservations = _api.GetReservationLogic.ReadList(null);
|
||||
var guests = _api.GetGuestLogic.ReadList(null);
|
||||
var cleaning = _api.GetCleaningLogic.ReadList(null).Last();
|
||||
|
||||
ViewBag.GuestCount = guests.Count;
|
||||
ViewBag.GuestLivingCount = reservations.GroupBy(x => x.GuestId).Count();
|
||||
ViewBag.GuestLiving = Math.Round((double)ViewBag.GuestLivingCount / guests.Count * 100);
|
||||
|
||||
ViewBag.MaxDay = reservations.Max(x => x.EndDate - x.StartDate).Days;
|
||||
ViewBag.AverageDay = reservations.Select(x => x.EndDate - x.StartDate)
|
||||
.Select(x => x.Days).Average();
|
||||
|
||||
ViewBag.MaxCost = reservations.Max(x => x.GetCost());
|
||||
ViewBag.AverageCost = reservations.Select(x => x.GetCost()).Average();
|
||||
|
||||
ViewBag.LastReservation = reservations.Last();
|
||||
ViewBag.LastReservationRooms = string.Join(",", reservations.Last().ReservationsRooms
|
||||
.Select(x => x.Key));
|
||||
ViewBag.LastCleaning = cleaning;
|
||||
|
||||
return View();
|
||||
}
|
||||
|
||||
public IActionResult Privacy()
|
||||
{
|
||||
if (_api.Maitre is null)
|
||||
{
|
||||
return View();
|
||||
return Redirect("~/Home/Login");
|
||||
}
|
||||
|
||||
public IActionResult Privacy()
|
||||
ViewBag.Maitre = _api.Maitre;
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Login()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public void Login(string login, string password)
|
||||
{
|
||||
if (string.IsNullOrEmpty(login) ||
|
||||
string.IsNullOrEmpty(password))
|
||||
{
|
||||
return View();
|
||||
throw new Exception("Enter login and password");
|
||||
}
|
||||
_api.Auth(login, password);
|
||||
if (_api.Maitre == null)
|
||||
{
|
||||
throw new Exception("Invalid login or password");
|
||||
}
|
||||
Response.Redirect("Index");
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Register()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public void Register(string login, string password, string passwordConfirm, string fio)
|
||||
{
|
||||
if (string.IsNullOrEmpty(login) ||
|
||||
string.IsNullOrEmpty(password) ||
|
||||
string.IsNullOrEmpty(fio) ||
|
||||
string.IsNullOrEmpty(passwordConfirm))
|
||||
{
|
||||
throw new Exception("Enter login and password");
|
||||
}
|
||||
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public IActionResult Error()
|
||||
if (!password.Equals(passwordConfirm))
|
||||
{
|
||||
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
|
||||
throw new Exception("Password must be equals");
|
||||
}
|
||||
|
||||
var fioSplit = fio.Split(" ");
|
||||
_api.Register(login, password, fioSplit[0], fioSplit[1], fioSplit[2]);
|
||||
Response.Redirect("Login");
|
||||
}
|
||||
|
||||
public IActionResult Rooms()
|
||||
{
|
||||
ViewBag.Maitre = _api.Maitre;
|
||||
return View(_api.GetRoomLogic.ReadList(null));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public void CreateRoom(string type, double cost)
|
||||
{
|
||||
if (string.IsNullOrEmpty(type) || cost == 0)
|
||||
{
|
||||
throw new Exception("Invalid arguments");
|
||||
}
|
||||
|
||||
_api.GetRoomLogic.Create(new RoomBindingModel
|
||||
{
|
||||
Cost = cost,
|
||||
Type = type
|
||||
});
|
||||
Response.Redirect("Rooms");
|
||||
}
|
||||
|
||||
public IActionResult Guests()
|
||||
{
|
||||
ViewBag.Maitre = _api.Maitre;
|
||||
return View(_api.GetGuestLogic.ReadList(null));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public void CreateGuest(string name, string secondName, string lastName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(secondName) || string.IsNullOrEmpty(lastName))
|
||||
{
|
||||
throw new Exception("Invalid arguments");
|
||||
}
|
||||
|
||||
_api.GetGuestLogic.Create(new GuestBindingModel
|
||||
{
|
||||
Name = name.FirstCharToUpper(),
|
||||
SecondName = secondName.FirstCharToUpper(),
|
||||
LastName = lastName.FirstCharToUpper()
|
||||
});
|
||||
Response.Redirect("Guests");
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper.DPA", "DPA0000: DPA issues")]
|
||||
public IActionResult Reservations()
|
||||
{
|
||||
ViewBag.Maitre = _api.Maitre;
|
||||
ViewBag.Guests = _api.GetGuestLogic.ReadList(null);
|
||||
ViewBag.Rooms = _api.GetRoomLogic.ReadList(new RoomSearchModel
|
||||
{
|
||||
IsReserved = false
|
||||
});
|
||||
var list = _api.GetReservationLogic.ReadList(null);
|
||||
return View(list);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public void CreateReservation(int clientId, DateTime dateStart, DateTime dateEnd, List<int> rooms, string cleaning)
|
||||
{
|
||||
if (dateEnd < dateStart || dateStart < DateTime.Now)
|
||||
{
|
||||
throw new Exception("Invalid arguments");
|
||||
}
|
||||
_api.GetReservationLogic.Create(new ReservationBindingModel
|
||||
{
|
||||
MaitreId = _api.Maitre.Id,
|
||||
GuestId = clientId,
|
||||
StartDate = dateStart,
|
||||
EndDate = dateEnd,
|
||||
ReservationsRooms = _api.GetRoomLogic.ReadList(null)
|
||||
.Where(x => rooms.Contains(x.Id))
|
||||
.ToDictionary(x => x.Id, y => y as IRoomModel)
|
||||
});
|
||||
if (string.Equals(cleaning, "on", StringComparison.Ordinal))
|
||||
{
|
||||
var clInst = _api.GetCleaningInstrumentsLogic.ReadList(null);
|
||||
foreach(var id in rooms)
|
||||
{
|
||||
_api.GetCleaningLogic.Create(new CleaningBindingModel
|
||||
{
|
||||
Date = dateEnd,
|
||||
RoomId = id,
|
||||
CleaningInstruments = clInst
|
||||
.Where(x => x.Id <= 4)
|
||||
.ToDictionary(x => x.Id,
|
||||
x => x as ICleaningInstrumentsModel)
|
||||
});
|
||||
}
|
||||
}
|
||||
Response.Redirect("Reservations");
|
||||
}
|
||||
|
||||
public IActionResult CleaningInstruments()
|
||||
{
|
||||
ViewBag.Maitre = _api.Maitre;
|
||||
return View(_api.GetCleaningInstrumentsLogic.ReadList(null));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public void CreateCleaningInstrument(string type)
|
||||
{
|
||||
if (string.IsNullOrEmpty(type))
|
||||
throw new ArgumentException("Type must be not null");
|
||||
_api.GetCleaningInstrumentsLogic.Create(new CleaningInstrumentsBindingModel
|
||||
{
|
||||
Type = type
|
||||
});
|
||||
Response.Redirect("CleaningInstruments");
|
||||
}
|
||||
|
||||
public IActionResult Cleaning()
|
||||
{
|
||||
ViewBag.Maitre = _api.Maitre;
|
||||
ViewBag.CleaningInstruments = _api.GetCleaningInstrumentsLogic.ReadList(null);
|
||||
ViewBag.Rooms = _api.GetRoomLogic.ReadList(null);
|
||||
return View(_api.GetCleaningLogic.ReadList(null));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public void CreateCleaning(int roomId, DateTime dateTime, List<int> cleanings)
|
||||
{
|
||||
if (roomId == 0)
|
||||
{
|
||||
throw new ArgumentException("Room id must be more then zero");
|
||||
}
|
||||
_api.GetCleaningLogic.Create(new CleaningBindingModel
|
||||
{
|
||||
RoomId = roomId,
|
||||
Date = dateTime,
|
||||
CleaningInstruments = _api.GetCleaningInstrumentsLogic.ReadList(null)
|
||||
.Where(x => cleanings.Contains(x.Id))
|
||||
.ToDictionary(x => x.Id,
|
||||
x => x as ICleaningInstrumentsModel)
|
||||
});
|
||||
Response.Redirect("Cleaning");
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public void DeleteReservation(int id)
|
||||
{
|
||||
if (id == 0) return;
|
||||
_api.GetReservationLogic.Delete(new ReservationBindingModel
|
||||
{
|
||||
Id = id
|
||||
});
|
||||
Response.Redirect("Reservations");
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public void DeleteRoom(int id)
|
||||
{
|
||||
if (id == 0) return;
|
||||
_api.GetRoomLogic.Delete(new()
|
||||
{
|
||||
Id = id
|
||||
});
|
||||
Response.Redirect("Rooms");
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public void DeleteGuest(int id)
|
||||
{
|
||||
if (id == 0) return;
|
||||
_api.GetGuestLogic.Delete(new()
|
||||
{
|
||||
Id = id
|
||||
});
|
||||
Response.Redirect("Guests");
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public void DeleteClean(int id)
|
||||
{
|
||||
if (id == 0) return;
|
||||
_api.GetCleaningLogic.Delete(new()
|
||||
{
|
||||
Id = id
|
||||
});
|
||||
Response.Redirect("Cleanings");
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public void DeleteInstrument(int id)
|
||||
{
|
||||
if (id == 0) return;
|
||||
_api.GetCleaningInstrumentsLogic.Delete(new()
|
||||
{
|
||||
Id = id
|
||||
});
|
||||
Response.Redirect("CleaningInstruments");
|
||||
}
|
||||
|
||||
public IActionResult Report()
|
||||
{
|
||||
ViewBag.Maitre = _api.Maitre;
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public void CreateWordReport()
|
||||
{
|
||||
_api.SendReportWord();
|
||||
Response.Redirect("Report");
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public void CreateExcelReport()
|
||||
{
|
||||
_api.SendReportExcel();
|
||||
Response.Redirect("Report");
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public void CreatePdfReport(DateTime from, DateTime to)
|
||||
{
|
||||
_api.SendReportPdf(from, to);
|
||||
Response.Redirect("Report");
|
||||
}
|
||||
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public IActionResult Error()
|
||||
{
|
||||
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0-preview.2.23128.3" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@ -20,4 +21,12 @@
|
||||
<ProjectReference Include="..\HotelDatabaseImplement\HotelDatabaseImplement.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="TempDirectoryForReports" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="wwwroot\css\index.css" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,15 +1,56 @@
|
||||
using HotelBusinessLogic.BusinessLogics;
|
||||
using HotelBusinessLogic.MailWorker;
|
||||
using HotelBusinessLogic.OfficePackage;
|
||||
using HotelBusinessLogic.OfficePackage.Implements;
|
||||
using HotelContracts.BindingModels;
|
||||
using HotelContracts.BusinessLogicsContracts;
|
||||
using HotelContracts.StoragesContracts;
|
||||
using HotelDatabaseImplement.Implements;
|
||||
using HotelView;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddControllersWithViews();
|
||||
builder.Services.AddTransient<IMaitreStorage, MaitreStorage>();
|
||||
builder.Services.AddTransient<IRoomStorage, RoomStorage>();
|
||||
builder.Services.AddTransient<IGuestStorage, GuestStorage>();
|
||||
builder.Services.AddTransient<IReservationStorage, ReservationStorage>();
|
||||
builder.Services.AddTransient<ICleaningInstrumentsStorage, CleaningInstrumentsStorage>();
|
||||
builder.Services.AddTransient<ICleaningStorage, CleaningStorage>();
|
||||
|
||||
builder.Services.AddTransient<AbstractSaveToExcel, SaveToExcel>();
|
||||
builder.Services.AddTransient<AbstractSaveToPdf, SaveToPdf>();
|
||||
builder.Services.AddTransient<AbstractSaveToWord, SaveToWord>();
|
||||
|
||||
builder.Services.AddTransient<IReportLogic, ReportLogic>();
|
||||
builder.Services.AddTransient<ICleaningLogic, CleaningLogic>();
|
||||
builder.Services.AddTransient<ICleaningInstrumentsLogic, CleaningInstrumentsLogic>();
|
||||
builder.Services.AddTransient<IReservationLogic, ReservationLogic>();
|
||||
builder.Services.AddTransient<IGuestLogic, GuestLogic>();
|
||||
builder.Services.AddTransient<IRoomLogic, RoomLogic>();
|
||||
builder.Services.AddTransient<IMaitreLogic, MaitreLogic>();
|
||||
|
||||
builder.Services.AddSingleton<AbstractMailWorker, MailKitWorker>();
|
||||
builder.Services.AddSingleton<Api>();
|
||||
|
||||
var app = builder.Build();
|
||||
var mailSender = app.Services.GetService<AbstractMailWorker>();
|
||||
mailSender?.MailConfig(new MailConfigBindingModel
|
||||
{
|
||||
MailLogin = builder.Configuration?.GetSection("MailLogin")?.Value ?? string.Empty,
|
||||
MailPassword = builder.Configuration?.GetSection("MailPassword")?.Value ?? string.Empty,
|
||||
SmtpClientHost = builder.Configuration?.GetSection("SmtpClientHost")?.Value ?? string.Empty,
|
||||
SmtpClientPort = Convert.ToInt32(builder.Configuration?.GetSection("SmtpClientPort")?.Value),
|
||||
PopHost = builder.Configuration?.GetSection("PopHost")?.Value ?? string.Empty,
|
||||
PopPort = Convert.ToInt32(builder.Configuration?.GetSection("PopPort")?.Value)
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (!app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseExceptionHandler("/Home/Error");
|
||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
|
12
Hotel/HotelView/Utils/StringExtensions.cs
Normal file
12
Hotel/HotelView/Utils/StringExtensions.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace HotelView.Utils;
|
||||
|
||||
public static class StringExtensions
|
||||
{
|
||||
public static string FirstCharToUpper(this string input) =>
|
||||
input switch
|
||||
{
|
||||
null => throw new ArgumentNullException(nameof(input)),
|
||||
"" => throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input)),
|
||||
_ => string.Concat(input[0].ToString().ToUpper(), input.AsSpan(1))
|
||||
};
|
||||
}
|
98
Hotel/HotelView/Views/Home/Cleaning.cshtml
Normal file
98
Hotel/HotelView/Views/Home/Cleaning.cshtml
Normal file
@ -0,0 +1,98 @@
|
||||
@model List<HotelContracts.ViewModels.CleaningViewModel>
|
||||
@{
|
||||
ViewData["Title"] = "Уборки";
|
||||
Layout = "_Layout";
|
||||
}
|
||||
|
||||
<div class="">
|
||||
<button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored" id="create">
|
||||
Новая уборка
|
||||
</button>
|
||||
@{
|
||||
<ul class="demo-list-two mdl-list">
|
||||
@foreach (var item in Model)
|
||||
{
|
||||
<li class="mdl-list__item" style="padding: 0 0 16px;">
|
||||
<div class="demo-card-wide mdl-card mdl-shadow--2dp" style="width: 100%;">
|
||||
<div class="mdl-card__title">
|
||||
<h2 class="mdl-card__title-text">Уборка @item.Date.ToShortDateString()</h2>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">
|
||||
<span>Номер: #@item.Room.Id</span>
|
||||
<ul class="demo-list-item mdl-list">
|
||||
@{
|
||||
@foreach (var room in item.CleaningInstruments)
|
||||
{
|
||||
<li class="mdl-list__item">
|
||||
<span class="mdl-list__item-primary-content">
|
||||
Комплект для уборки №@room.Value.Id @room.Value.Type
|
||||
</span>
|
||||
</li>
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
<span>Всего инструментов @item.CleaningInstruments.Count</span>
|
||||
</div>
|
||||
<div class="mdl-card__actions mdl-card--border">
|
||||
<a
|
||||
href="/Home/DeleteClean?id=@item.Id"
|
||||
class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
|
||||
Удалить
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
<dialog class="mdl-dialog">
|
||||
<h4 class="mdl-dialog__title">Добавление уборки</h4>
|
||||
<form method="post" asp-controller="Home" asp-action="CreateCleaning">
|
||||
<div class="mdl-dialog__content">
|
||||
<span>Дата уборки</span>
|
||||
<div class="mdl-textfield mdl-js-textfield">
|
||||
<input class="mdl-textfield__input" type="date" id="date" name="dateTime">
|
||||
</div>
|
||||
|
||||
<span>Номер</span>
|
||||
<div class="mdl-textfield mdl-js-textfield">
|
||||
<select name="roomId" id="rooms" class="mdl-textfield__input">
|
||||
@{
|
||||
@foreach (var room in ViewBag.Rooms)
|
||||
{
|
||||
<option value="@room.Id">#@room.Id @room.GetTypeRoom()</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<span>Инструменты для уборки</span>
|
||||
<div class="mdl-textfield mdl-js-textfield">
|
||||
<select name="cleanings" id="" class="mdl-textfield__input" multiple="multiple">
|
||||
@{
|
||||
@foreach (var item in ViewBag.CleaningInstruments)
|
||||
{
|
||||
<option value="@item.Id">#@item.Id @item.Type</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mdl-dialog__actions">
|
||||
<button type="submit" class="mdl-button">Добавить</button>
|
||||
<button type="button" class="mdl-button close">Отмена</button>
|
||||
</div>
|
||||
</form>
|
||||
</dialog>
|
||||
</div>
|
||||
<script>
|
||||
const dialog = document.querySelector('dialog');
|
||||
const showDialogButton = document.querySelector('#create');
|
||||
|
||||
showDialogButton.addEventListener('click', function() {
|
||||
dialog.showModal();
|
||||
});
|
||||
dialog.querySelector('.close').addEventListener('click', function() {
|
||||
dialog.close();
|
||||
});
|
||||
</script>
|
55
Hotel/HotelView/Views/Home/CleaningInstruments.cshtml
Normal file
55
Hotel/HotelView/Views/Home/CleaningInstruments.cshtml
Normal file
@ -0,0 +1,55 @@
|
||||
@model List<HotelContracts.ViewModels.CleaningInstrumentsViewModel>
|
||||
@{
|
||||
ViewData["Title"] = "Инструменты для уборки";
|
||||
Layout = "_Layout";
|
||||
}
|
||||
|
||||
<div class="">
|
||||
<button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored" id="create">
|
||||
Добавить инструмент уборки
|
||||
</button>
|
||||
@{
|
||||
<ul class="demo-list-two mdl-list">
|
||||
@foreach (var item in Model)
|
||||
{
|
||||
<li class="mdl-list__item">
|
||||
<span class="mdl-list__item-primary-content">
|
||||
<i class="material-icons mdl-list__item-icon">cleaning_services</i>
|
||||
#@item.Id - @item.Type
|
||||
</span>
|
||||
<a
|
||||
href="/Home/DeleteInstrument?id=@item.Id"
|
||||
class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
|
||||
Удалить
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
<dialog class="mdl-dialog">
|
||||
<h4 class="mdl-dialog__title">Добавление иструмента</h4>
|
||||
<form method="post" asp-controller="Home" asp-action="CreateCleaningInstrument">
|
||||
<div class="mdl-dialog__content">
|
||||
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||
<input class="mdl-textfield__input" type="text" id="secondName" name="type">
|
||||
<label class="mdl-textfield__label" for="secondName">Название</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mdl-dialog__actions">
|
||||
<button type="submit" class="mdl-button">Добавить</button>
|
||||
<button type="button" class="mdl-button close">Отмена</button>
|
||||
</div>
|
||||
</form>
|
||||
</dialog>
|
||||
</div>
|
||||
<script>
|
||||
const dialog = document.querySelector('dialog');
|
||||
const showDialogButton = document.querySelector('#create');
|
||||
|
||||
showDialogButton.addEventListener('click', function() {
|
||||
dialog.showModal();
|
||||
});
|
||||
dialog.querySelector('.close').addEventListener('click', function() {
|
||||
dialog.close();
|
||||
});
|
||||
</script>
|
63
Hotel/HotelView/Views/Home/Guests.cshtml
Normal file
63
Hotel/HotelView/Views/Home/Guests.cshtml
Normal file
@ -0,0 +1,63 @@
|
||||
@model List<HotelContracts.ViewModels.GuestViewModel>
|
||||
@{
|
||||
ViewData["Title"] = "Гости";
|
||||
Layout = "_Layout";
|
||||
}
|
||||
|
||||
<div class="">
|
||||
<button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored" id="create">
|
||||
Добавить постояльца
|
||||
</button>
|
||||
@{
|
||||
<ul class="demo-list-two mdl-list">
|
||||
@foreach (var item in Model)
|
||||
{
|
||||
<li class="mdl-list__item">
|
||||
<span class="mdl-list__item-primary-content">
|
||||
<i class="material-icons mdl-list__item-icon">person</i>
|
||||
#@item.Id - @item.Fio
|
||||
</span>
|
||||
<a
|
||||
href="/Home/DeleteGuest?id=@item.Id"
|
||||
class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
|
||||
Удалить
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
<dialog class="mdl-dialog">
|
||||
<h4 class="mdl-dialog__title">Добавление гостя</h4>
|
||||
<form method="post" asp-controller="Home" asp-action="CreateGuest">
|
||||
<div class="mdl-dialog__content">
|
||||
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||
<input class="mdl-textfield__input" type="text" id="secondName" name="secondName">
|
||||
<label class="mdl-textfield__label" for="secondName">Фамилия</label>
|
||||
</div>
|
||||
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||
<input class="mdl-textfield__input" type="text" id="name" name="name">
|
||||
<label class="mdl-textfield__label" for="name">Имя</label>
|
||||
</div>
|
||||
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||
<input class="mdl-textfield__input" type="text" id="LastName" name="LastName">
|
||||
<label class="mdl-textfield__label" for="LastName">Отчество</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mdl-dialog__actions">
|
||||
<button type="submit" class="mdl-button">Добавить</button>
|
||||
<button type="button" class="mdl-button close">Отмена</button>
|
||||
</div>
|
||||
</form>
|
||||
</dialog>
|
||||
</div>
|
||||
<script>
|
||||
const dialog = document.querySelector('dialog');
|
||||
const showDialogButton = document.querySelector('#create');
|
||||
|
||||
showDialogButton.addEventListener('click', function() {
|
||||
dialog.showModal();
|
||||
});
|
||||
dialog.querySelector('.close').addEventListener('click', function() {
|
||||
dialog.close();
|
||||
});
|
||||
</script>
|
@ -1,8 +1,52 @@
|
||||
@{
|
||||
ViewData["Title"] = "Home Page";
|
||||
Layout = "_Layout";
|
||||
}
|
||||
|
||||
<div class="text-center">
|
||||
<h1 class="display-4">Welcome</h1>
|
||||
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
|
||||
<link rel="stylesheet" href="~/css/index.css">
|
||||
<div class="">
|
||||
<div class="demo-charts mdl-color--white mdl-shadow--2dp mdl-cell mdl-cell--12-col mdl-grid">
|
||||
<div class="pie animate no-round" style="--p:@ViewBag.RoomIsReserved;">@ViewBag.RoomIsReserved%</div>
|
||||
<h6>Номеров забронировано (@ViewBag.RoomIsReservedCount из @ViewBag.RoomAll)</h6>
|
||||
</div>
|
||||
<div class="demo-charts mdl-color--white mdl-shadow--2dp mdl-cell mdl-cell--12-col mdl-grid">
|
||||
<div class="pie animate no-round" style="--p:@ViewBag.GuestLiving;">@ViewBag.GuestLiving%</div>
|
||||
<h6>Постояльцев проживает (@ViewBag.GuestLivingCount из @ViewBag.GuestCount)</h6>
|
||||
</div>
|
||||
<div class="demo-charts mdl-color--white mdl-shadow--2dp mdl-cell mdl-cell--12-col mdl-grid">
|
||||
<div class="line" style="--value:@Math.Round(ViewBag.AverageDay);--max: @ViewBag.MaxDay">
|
||||
<div class="line_min">0</div>
|
||||
<div class="line_value">@ViewBag.AverageDay</div>
|
||||
<div class="line_max">@ViewBag.MaxDay</div>
|
||||
</div>
|
||||
<h6 class="line_label">Среднее время проживания (в днях)</h6>
|
||||
</div>
|
||||
<div class="demo-charts mdl-color--white mdl-shadow--2dp mdl-cell mdl-cell--12-col mdl-grid">
|
||||
<div class="line" style="--value:@ViewBag.AverageCost;--max:@ViewBag.MaxCost;">
|
||||
<div class="line_min">0</div>
|
||||
<div class="line_value">@ViewBag.AverageCost</div>
|
||||
<div class="line_max">@ViewBag.MaxCost</div>
|
||||
</div>
|
||||
<h6 class="line_label">Средний чек (в рублях)</h6>
|
||||
</div>
|
||||
<div class="demo-charts mdl-color--white mdl-shadow--2dp mdl-cell mdl-cell--12-col mdl-grid">
|
||||
<h6 class="info">Последнее бронирование</h6>
|
||||
<span class="info">
|
||||
<i class="material-icons mdl-list__item-icon">event_seat</i>
|
||||
<span>
|
||||
<b>С</b> @ViewBag.LastReservation.StartDate.ToShortDateString()
|
||||
<b>по</b> @ViewBag.LastReservation.EndDate.ToShortDateString()
|
||||
</span>
|
||||
<span><b>Номер:</b> @ViewBag.LastReservationRooms</span>
|
||||
<span><b>Клиент:</b> @ViewBag.LastReservation.Guest.Fio</span>
|
||||
<span><b>На сумму</b> @ViewBag.LastReservation.GetCost()</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="demo-charts mdl-color--white mdl-shadow--2dp mdl-cell mdl-cell--12-col mdl-grid">
|
||||
<h6 class="info">Последняя уборка</h6>
|
||||
<span class="info-start">
|
||||
<i class="material-icons mdl-list__item-icon">wash</i>
|
||||
<span><b>Дата </b> @ViewBag.LastCleaning.Date</span>
|
||||
<span><b>Номер:</b> @ViewBag.LastCleaning.Room.Id</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
44
Hotel/HotelView/Views/Home/Register.cshtml
Normal file
44
Hotel/HotelView/Views/Home/Register.cshtml
Normal file
@ -0,0 +1,44 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<link rel="stylesheet" href="https://code.getmdl.io/1.3.0/material.indigo-pink.min.css">
|
||||
<link rel="stylesheet" href="~/css/site.css">
|
||||
<script defer src="https://code.getmdl.io/1.3.0/material.min.js"></script>
|
||||
<title>Регистрация</title>
|
||||
</head>
|
||||
<body>
|
||||
<form method="post" class="auth">
|
||||
<div class="auth-cont">
|
||||
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||
<input class="mdl-textfield__input" type="email" id="login" name="login">
|
||||
<label class="mdl-textfield__label" for="login">Логин</label>
|
||||
</div>
|
||||
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||
<input class="mdl-textfield__input" type="text" id="name" name="fio">
|
||||
<label class="mdl-textfield__label" for="name">Фио</label>
|
||||
</div>
|
||||
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||
<input class="mdl-textfield__input" type="password" id="password" name="password">
|
||||
<label class="mdl-textfield__label" for="password">Пароль</label>
|
||||
</div>
|
||||
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||
<input class="mdl-textfield__input" type="password" id="password1" name="passwordConfirm">
|
||||
<label class="mdl-textfield__label" for="password1">Подтвердите пароль</label>
|
||||
</div>
|
||||
<div class="auth-btn">
|
||||
<button type="submit" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
|
||||
Регистрация
|
||||
</button>
|
||||
<a class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent"
|
||||
asp-controller="Home"
|
||||
asp-action="Login">
|
||||
Назад
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
49
Hotel/HotelView/Views/Home/Report.cshtml
Normal file
49
Hotel/HotelView/Views/Home/Report.cshtml
Normal file
@ -0,0 +1,49 @@
|
||||
@model List<HotelContracts.ViewModels.RoomViewModel>
|
||||
@{
|
||||
ViewData["Title"] = "Отчеты";
|
||||
Layout = "_Layout";
|
||||
}
|
||||
<link rel="stylesheet" href="~/css/index.css">
|
||||
<div class="">
|
||||
<div class="demo-charts mdl-color--white mdl-shadow--2dp mdl-cell mdl-cell--12-col mdl-grid" style="padding: 1rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;">
|
||||
<h6>Создать отчет в формате (.docx) и отправить его на почту @ViewBag.Maitre.Login</h6>
|
||||
<a asp-controller="Home"
|
||||
asp-action="CreateWordReport"
|
||||
class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
|
||||
Отправить
|
||||
</a>
|
||||
</div>
|
||||
<div class="demo-charts mdl-color--white mdl-shadow--2dp mdl-cell mdl-cell--12-col mdl-grid" style="padding: 1rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;">
|
||||
<h6>Создать отчет в формате (.xlsx) и отправить его на почту @ViewBag.Maitre.Login</h6>
|
||||
<a asp-controller="Home"
|
||||
asp-action="CreateExcelReport"
|
||||
class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
|
||||
Отправить
|
||||
</a>
|
||||
</div>
|
||||
<div class="demo-charts mdl-color--white mdl-shadow--2dp mdl-cell mdl-cell--12-col mdl-grid" style="padding: 1rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;">
|
||||
<h6 class="line_label">Создать отчет в формате (.pdf) и отправить его на почту @ViewBag.Maitre.Login</h6>
|
||||
<form asp-controller="Home" asp-action="CreatePdfReport" method="post">
|
||||
<span>Начальная дата</span>
|
||||
<div class="mdl-textfield mdl-js-textfield">
|
||||
<input class="mdl-textfield__input" type="date" name="from">
|
||||
</div>
|
||||
<span>Конечная дата</span>
|
||||
<div class="mdl-textfield mdl-js-textfield">
|
||||
<input class="mdl-textfield__input" type="date" name="to">
|
||||
</div>
|
||||
<button type="submit" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
|
||||
Отправить
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
107
Hotel/HotelView/Views/Home/Reservations.cshtml
Normal file
107
Hotel/HotelView/Views/Home/Reservations.cshtml
Normal file
@ -0,0 +1,107 @@
|
||||
@using HotelContracts.ViewModels
|
||||
@model List<HotelContracts.ViewModels.ReservationViewModel>
|
||||
@{
|
||||
ViewData["Title"] = "Бронирования";
|
||||
Layout = "_Layout";
|
||||
}
|
||||
|
||||
<div class="">
|
||||
<button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored" id="create">
|
||||
Новое бронирование
|
||||
</button>
|
||||
@{
|
||||
<ul class="demo-list-two mdl-list">
|
||||
@foreach (var item in Model)
|
||||
{
|
||||
<li class="mdl-list__item" style="
|
||||
padding: 0 0 16px;
|
||||
">
|
||||
<div class="demo-card-wide mdl-card mdl-shadow--2dp" style="width: 100%;">
|
||||
<div class="mdl-card__title">
|
||||
<h2 class="mdl-card__title-text">Бронирование с @item.StartDate.ToShortDateString() по @item.EndDate.ToShortDateString()</h2>
|
||||
</div>
|
||||
<div class="mdl-card__supporting-text">
|
||||
<span>Постоялец: @item.Guest.Fio</span>
|
||||
<ul class="demo-list-item mdl-list">
|
||||
@{
|
||||
@foreach (var room in item.ReservationsRooms)
|
||||
{
|
||||
<li class="mdl-list__item">
|
||||
<span class="mdl-list__item-primary-content">
|
||||
Номер №@room.Value.Id стоимость за день: @room.Value.Cost
|
||||
</span>
|
||||
</li>
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
<span>Общая стоимость @item.GetCost() рублей</span>
|
||||
</div>
|
||||
<div class="mdl-card__actions mdl-card--border">
|
||||
<a
|
||||
href="/Home/DeleteReservation?id=@item.Id"
|
||||
class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
|
||||
Удалить
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
<dialog class="mdl-dialog">
|
||||
<h4 class="mdl-dialog__title">Новое бронирование</h4>
|
||||
<form method="post" asp-controller="Home" asp-action="CreateReservation">
|
||||
<div class="mdl-dialog__content">
|
||||
<span>Дата заселения</span>
|
||||
<div class="mdl-textfield mdl-js-textfield">
|
||||
<input class="mdl-textfield__input" type="date" id="dateStart" name="dateStart">
|
||||
</div>
|
||||
<span>Дата выселения</span>
|
||||
<div class="mdl-textfield mdl-js-textfield">
|
||||
<input class="mdl-textfield__input" type="date" id="dateEnd" name="dateEnd">
|
||||
</div>
|
||||
<div class="mdl-textfield mdl-js-textfield">
|
||||
<select name="clientId" id="guest" class="mdl-textfield__input">
|
||||
@{
|
||||
@foreach (var client in ViewBag.Guests)
|
||||
{
|
||||
<option value="@client.Id">@client.Fio</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
<span class="mdl-textfield__label" for="guest">Гость</span>
|
||||
</div>
|
||||
<span>Номер(а)</span>
|
||||
<div class="mdl-textfield mdl-js-textfield">
|
||||
<select name="rooms" id="rooms" class="mdl-textfield__input" multiple="multiple">
|
||||
@{
|
||||
@foreach (var room in ViewBag.Rooms)
|
||||
{
|
||||
<option value="@room.Id">#@room.Id @room.GetTypeRoom()</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" for="checkbox-1" name="cleaning">
|
||||
<input type="checkbox" id="checkbox-1" class="mdl-checkbox__input" name="cleaning" checked="checked">
|
||||
<span class="mdl-checkbox__label">Запланировать уборку?</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="mdl-dialog__actions">
|
||||
<button type="submit" class="mdl-button">Добавить</button>
|
||||
<button type="button" class="mdl-button close">Отмена</button>
|
||||
</div>
|
||||
</form>
|
||||
</dialog>
|
||||
</div>
|
||||
<script>
|
||||
const dialog = document.querySelector('dialog');
|
||||
const showDialogButton = document.querySelector('#create');
|
||||
|
||||
showDialogButton.addEventListener('click', function() {
|
||||
dialog.showModal();
|
||||
});
|
||||
dialog.querySelector('.close').addEventListener('click', function() {
|
||||
dialog.close();
|
||||
});
|
||||
</script>
|
98
Hotel/HotelView/Views/Home/Rooms.cshtml
Normal file
98
Hotel/HotelView/Views/Home/Rooms.cshtml
Normal file
@ -0,0 +1,98 @@
|
||||
@model List<HotelContracts.ViewModels.RoomViewModel>
|
||||
@{
|
||||
ViewData["Title"] = "Home Page";
|
||||
Layout = "_Layout";
|
||||
}
|
||||
|
||||
<div class="">
|
||||
<button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored" id="create">
|
||||
Добавить номер
|
||||
</button>
|
||||
@{
|
||||
<ul class="demo-list-two mdl-list">
|
||||
@foreach (var item in Model)
|
||||
{
|
||||
<li class="mdl-list__item mdl-list__item--two-line">
|
||||
<span class="mdl-list__item-primary-content">
|
||||
@{
|
||||
switch (item.Type)
|
||||
{
|
||||
case "standard":
|
||||
<i class="material-icons mdl-list__item-avatar">chair</i>
|
||||
break;
|
||||
case "superior":
|
||||
<i class="material-icons mdl-list__item-avatar">weekend</i>
|
||||
break;
|
||||
case "bedroom":
|
||||
<i class="material-icons mdl-list__item-avatar">bed</i>
|
||||
break;
|
||||
case "apartment":
|
||||
<i class="material-icons mdl-list__item-avatar">apartment</i>
|
||||
break;
|
||||
case "studio":
|
||||
<i class="material-icons mdl-list__item-avatar">yard</i>
|
||||
break;
|
||||
case "suite":
|
||||
<i class="material-icons mdl-list__item-avatar">spa</i>
|
||||
break;
|
||||
}
|
||||
}
|
||||
<span>Номер: №@item.Id</span>
|
||||
<span class="mdl-list__item-sub-title">Стоимость за сутки: @item.Cost рублей</span>
|
||||
</span>
|
||||
@{
|
||||
if (item.IsReserved)
|
||||
{
|
||||
<span>Забронирована</span>
|
||||
}
|
||||
}
|
||||
<span class="mdl-list__item-secondary-content">
|
||||
<span class="mdl-list__item-secondary-info">@item.GetTypeRoom()</span>
|
||||
<a
|
||||
href="/Home/DeleteRoom?id=@item.Id"
|
||||
class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
|
||||
Удалить
|
||||
</a>
|
||||
</span>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
<dialog class="mdl-dialog">
|
||||
<h4 class="mdl-dialog__title">Добавление номера</h4>
|
||||
<form method="post" asp-controller="Home" asp-action="CreateRoom">
|
||||
<div class="mdl-dialog__content">
|
||||
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||
<input class="mdl-textfield__input" type="number" id="cost" name="cost">
|
||||
<label class="mdl-textfield__label" for="cost">Стоимость</label>
|
||||
</div>
|
||||
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||
<select class="mdl-textfield__input" name="type" id="type">
|
||||
<option value="standard">Стандартный</option>
|
||||
<option value="superior">Улучшенный</option>
|
||||
<option value="bedroom">Со спальной комнатой</option>
|
||||
<option value="apartment">Апартаменты/квартира</option>
|
||||
<option value="studio">Студия</option>
|
||||
<option value="suite">Люкс</option>
|
||||
</select>
|
||||
<label class="mdl-textfield__label" for="type">Вид номера</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mdl-dialog__actions">
|
||||
<button type="submit" class="mdl-button">Добавить</button>
|
||||
<button type="button" class="mdl-button close">Отмена</button>
|
||||
</div>
|
||||
</form>
|
||||
</dialog>
|
||||
</div>
|
||||
<script>
|
||||
const dialog = document.querySelector('dialog');
|
||||
const showDialogButton = document.querySelector('#create');
|
||||
|
||||
showDialogButton.addEventListener('click', function() {
|
||||
dialog.showModal();
|
||||
});
|
||||
dialog.querySelector('.close').addEventListener('click', function() {
|
||||
dialog.close();
|
||||
});
|
||||
</script>
|
43
Hotel/HotelView/Views/Home/_Layout.cshtml
Normal file
43
Hotel/HotelView/Views/Home/_Layout.cshtml
Normal file
@ -0,0 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
|
||||
<link rel="stylesheet" href="https://code.getmdl.io/1.3.0/material.indigo-pink.min.css">
|
||||
<link rel="stylesheet" href="~/css/site.css" runat="server">
|
||||
<script defer src="https://code.getmdl.io/1.3.0/material.min.js"></script>
|
||||
<title>@ViewData["Title"] - Hotel</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="demo-layout mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
|
||||
<header class="demo-header mdl-layout__header mdl-color--grey-100 mdl-color-text--grey-600">
|
||||
<div class="mdl-layout__header-row">
|
||||
<span class="mdl-layout-title">Гостиница Принцесса на горошине</span>
|
||||
</div>
|
||||
</header>
|
||||
<div class="demo-drawer mdl-layout__drawer mdl-color--blue-grey-900 mdl-color-text--blue-grey-50">
|
||||
<header class="demo-drawer-header">
|
||||
<div class="demo-avatar-dropdown">
|
||||
<img src="https://cdn.icon-icons.com/icons2/1465/PNG/512/156womanofficeworker2_100687.png" alt="-" class="demo-avatar">
|
||||
<span>@ViewBag.Maitre.Fio</span>
|
||||
</div>
|
||||
</header>
|
||||
<nav class="demo-navigation mdl-navigation mdl-color--blue-grey-800">
|
||||
<a class="mdl-navigation__link" asp-controller="Home" asp-action="Index"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">home</i>Домой</a>
|
||||
<a class="mdl-navigation__link" asp-controller="Home" asp-action="Rooms"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">bed</i>Номера</a>
|
||||
<a class="mdl-navigation__link" asp-controller="Home" asp-action="Reservations"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">event_seat</i>Бронирования</a>
|
||||
<a class="mdl-navigation__link" asp-controller="Home" asp-action="Guests"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">person</i>Постояльцы</a>
|
||||
<a class="mdl-navigation__link" asp-controller="Home" asp-action="Cleaning"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">wash</i>Уборки</a>
|
||||
<a class="mdl-navigation__link" asp-controller="Home" asp-action="CleaningInstruments"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">cleaning_services</i>Средства для уборки</a>
|
||||
<a class="mdl-navigation__link" asp-controller="Home" asp-action="Report"><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">report</i>Отчеты</a>
|
||||
<div class="mdl-layout-spacer"></div>
|
||||
<a class="mdl-navigation__link" href=""><i class="mdl-color-text--blue-grey-400 material-icons" role="presentation">help_outline</i><span class="visuallyhidden">Help</span></a>
|
||||
</nav>
|
||||
</div>
|
||||
<main class="mdl-layout__content mdl-color--grey-100 main">
|
||||
@RenderBody()
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
36
Hotel/HotelView/Views/Home/login.cshtml
Normal file
36
Hotel/HotelView/Views/Home/login.cshtml
Normal file
@ -0,0 +1,36 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<link rel="stylesheet" href="https://code.getmdl.io/1.3.0/material.indigo-pink.min.css">
|
||||
<link rel="stylesheet" href="~/css/site.css">
|
||||
<script defer src="https://code.getmdl.io/1.3.0/material.min.js"></script>
|
||||
<title>Авторизация</title>
|
||||
</head>
|
||||
<body>
|
||||
<form method="post" class="auth">
|
||||
<div class="auth-cont">
|
||||
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||
<input class="mdl-textfield__input" type="email" id="login" name="login">
|
||||
<label class="mdl-textfield__label" for="login">Логин</label>
|
||||
</div>
|
||||
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||
<input class="mdl-textfield__input" type="password" id="password" name="password">
|
||||
<label class="mdl-textfield__label" for="password">Пароль</label>
|
||||
</div>
|
||||
<div class="auth-btn">
|
||||
<button type="submit" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
|
||||
Авторизация
|
||||
</button>
|
||||
<a class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent"
|
||||
asp-controller="Home"
|
||||
asp-action="Register">
|
||||
Регистрация
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
@ -1,49 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>@ViewData["Title"] - HotelView</title>
|
||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
|
||||
<link rel="stylesheet" href="~/HotelView.styles.css" asp-append-version="true" />
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">HotelView</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
|
||||
aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
|
||||
<ul class="navbar-nav flex-grow-1">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="container">
|
||||
<main role="main" class="pb-3">
|
||||
@RenderBody()
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="border-top footer text-muted">
|
||||
<div class="container">
|
||||
© 2023 - HotelView - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
|
||||
</div>
|
||||
</footer>
|
||||
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
||||
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||
@await RenderSectionAsync("Scripts", required: false)
|
||||
</body>
|
||||
</html>
|
@ -1,3 +1 @@
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
}
|
||||
|
||||
|
@ -5,5 +5,11 @@
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
"AllowedHosts": "*",
|
||||
"SmtpClientHost": "smtp.gmail.com",
|
||||
"SmtpClientPort": "587",
|
||||
"PopHost": "pop.gmail.com",
|
||||
"PopPort": "995",
|
||||
"MailLogin": "sushibarulyanosk7@gmail.com",
|
||||
"MailPassword": "qwzj uqlx uukp bpmc"
|
||||
}
|
||||
|
146
Hotel/HotelView/wwwroot/css/index.css
Normal file
146
Hotel/HotelView/wwwroot/css/index.css
Normal file
@ -0,0 +1,146 @@
|
||||
@property --p {
|
||||
syntax: "<number>";
|
||||
inherits: true;
|
||||
initial-value: 0;
|
||||
}
|
||||
|
||||
.pie {
|
||||
--p:20;
|
||||
--b:8px;
|
||||
--c:lightgreen;
|
||||
--w:90px;
|
||||
|
||||
width: var(--w);
|
||||
aspect-ratio:1;
|
||||
display:inline-grid;
|
||||
position: relative;
|
||||
place-content:center;
|
||||
font-size:25px;
|
||||
margin: 5px 20px 5px 5px;
|
||||
}
|
||||
|
||||
.pie:before,
|
||||
.pie:after {
|
||||
content:"";
|
||||
position:absolute;
|
||||
border-radius:50%;
|
||||
}
|
||||
.pie:before {
|
||||
inset:0;
|
||||
background:
|
||||
radial-gradient(farthest-side,var(--c) 98%,#0000) top/var(--b) var(--b) no-repeat,
|
||||
conic-gradient(var(--c) calc(var(--p)*1%),#0000 0);
|
||||
-webkit-mask:radial-gradient(farthest-side,#0000 calc(99% - var(--b)),#000 calc(100% - var(--b)));
|
||||
mask:radial-gradient(farthest-side,#0000 calc(99% - var(--b)),#000 calc(100% - var(--b)));
|
||||
}
|
||||
.pie:after {
|
||||
inset:calc(50% - var(--b)/2);
|
||||
background:var(--c);
|
||||
transform:rotate(calc(var(--p)*3.6deg)) translateY(calc(50% - var(--w)/2));
|
||||
}
|
||||
@keyframes p {
|
||||
from{--p:0}
|
||||
}
|
||||
.animate {
|
||||
animation:p 1s .5s both;
|
||||
}
|
||||
.no-round:before {
|
||||
background-size: 0 0, auto;
|
||||
}
|
||||
.no-round:after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
@property --value {
|
||||
syntax: "<number>";
|
||||
inherits: true;
|
||||
initial-value: 0;
|
||||
}
|
||||
|
||||
.line {
|
||||
--value: 8;
|
||||
--max: 10;
|
||||
|
||||
position: relative;
|
||||
margin: 1em;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
background-color: #343a405A;
|
||||
animation:l 1s .5s both;
|
||||
}
|
||||
|
||||
.line:after {
|
||||
content: "";
|
||||
display: block;
|
||||
height: 4px;
|
||||
top: -1px;
|
||||
position: absolute;
|
||||
background-color: lightgreen;
|
||||
width: calc(var(--value) / var(--max) * 100%);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.line:before {
|
||||
content: "";
|
||||
display: block;
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
top: -3px;
|
||||
position: absolute;
|
||||
background-color: lightgreen;
|
||||
left: calc(var(--value) / var(--max) * 100%);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.line * {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
color: #343a40;
|
||||
}
|
||||
|
||||
.line .line_max {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.line .line_value {
|
||||
left: calc(var(--value) / var(--max) * 100%);
|
||||
}
|
||||
|
||||
h6.line_label {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@keyframes l {
|
||||
from {--value: 0}
|
||||
}
|
||||
|
||||
h6.info {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
span.info {
|
||||
padding: 0 10px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
span.info-start {
|
||||
padding: 0 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
span.info-start * {
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.cont {
|
||||
padding: 1rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
@ -1,18 +1,263 @@
|
||||
html {
|
||||
font-size: 14px;
|
||||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
html {
|
||||
font-size: 16px;
|
||||
}
|
||||
.demo-layout-transparent {
|
||||
background: url("https://wallpaperaccess.com/full/812556.jpg") center / cover;
|
||||
}
|
||||
|
||||
html {
|
||||
.demo-layout-transparent .mdl-layout__header,
|
||||
.demo-layout-transparent .mdl-layout__drawer-button {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.demo-graph {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
html, body {
|
||||
font-family: 'Roboto', 'Helvetica', sans-serif;
|
||||
}
|
||||
.demo-avatar {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 24px;
|
||||
}
|
||||
.demo-layout .mdl-layout__header .mdl-layout__drawer-button {
|
||||
color: rgba(0, 0, 0, 0.54);
|
||||
}
|
||||
.mdl-layout__drawer .avatar {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.demo-drawer {
|
||||
border: none;
|
||||
}
|
||||
/* iOS Safari specific workaround */
|
||||
.demo-drawer .mdl-menu__container {
|
||||
z-index: -1;
|
||||
}
|
||||
.demo-drawer .demo-navigation {
|
||||
z-index: -2;
|
||||
}
|
||||
/* END iOS Safari specific workaround */
|
||||
.demo-drawer .mdl-menu .mdl-menu__item {
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-align-items: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
.demo-drawer-header {
|
||||
box-sizing: border-box;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-flex-direction: column;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-webkit-justify-content: flex-end;
|
||||
-ms-flex-pack: end;
|
||||
justify-content: flex-end;
|
||||
padding: 16px;
|
||||
height: 151px;
|
||||
}
|
||||
.demo-avatar-dropdown {
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
-webkit-flex-direction: row;
|
||||
-ms-flex-direction: row;
|
||||
flex-direction: row;
|
||||
-webkit-align-items: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.demo-navigation {
|
||||
-webkit-flex-grow: 1;
|
||||
-ms-flex-positive: 1;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.demo-layout .demo-navigation .mdl-navigation__link {
|
||||
display: -webkit-flex !important;
|
||||
display: -ms-flexbox !important;
|
||||
display: flex !important;
|
||||
-webkit-flex-direction: row;
|
||||
-ms-flex-direction: row;
|
||||
flex-direction: row;
|
||||
-webkit-align-items: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
color: rgba(255, 255, 255, 0.56);
|
||||
font-weight: 500;
|
||||
}
|
||||
.demo-layout .demo-navigation .mdl-navigation__link:hover {
|
||||
background-color: #00BCD4;
|
||||
color: #37474F;
|
||||
}
|
||||
.demo-navigation .mdl-navigation__link .material-icons {
|
||||
font-size: 24px;
|
||||
color: rgba(255, 255, 255, 0.56);
|
||||
margin-right: 32px;
|
||||
}
|
||||
|
||||
.demo-content {
|
||||
max-width: 1080px;
|
||||
}
|
||||
|
||||
.demo-charts {
|
||||
-webkit-align-items: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
.demo-chart:nth-child(1) {
|
||||
color: #ACEC00;
|
||||
}
|
||||
.demo-chart:nth-child(2) {
|
||||
color: #00BBD6;
|
||||
}
|
||||
.demo-chart:nth-child(3) {
|
||||
color: #BA65C9;
|
||||
}
|
||||
.demo-chart:nth-child(4) {
|
||||
color: #EF3C79;
|
||||
}
|
||||
.demo-graphs {
|
||||
padding: 16px 32px;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-flex-direction: column;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-webkit-align-items: stretch;
|
||||
-ms-flex-align: stretch;
|
||||
align-items: stretch;
|
||||
}
|
||||
_:-ms-input-placeholder, :root .demo-graphs {
|
||||
min-height: 664px;
|
||||
}
|
||||
_:-ms-input-placeholder, :root .demo-graph {
|
||||
max-height: 300px;
|
||||
}
|
||||
/* TODO end */
|
||||
.demo-graph:nth-child(1) {
|
||||
color: #00b9d8;
|
||||
}
|
||||
.demo-graph:nth-child(2) {
|
||||
color: #d9006e;
|
||||
}
|
||||
|
||||
.demo-cards {
|
||||
-webkit-align-items: flex-start;
|
||||
-ms-flex-align: start;
|
||||
align-items: flex-start;
|
||||
-webkit-align-content: flex-start;
|
||||
-ms-flex-line-pack: start;
|
||||
align-content: flex-start;
|
||||
}
|
||||
.demo-cards .demo-separator {
|
||||
height: 32px;
|
||||
}
|
||||
.demo-cards .mdl-card__title.mdl-card__title {
|
||||
color: white;
|
||||
font-size: 24px;
|
||||
font-weight: 400;
|
||||
}
|
||||
.demo-cards ul {
|
||||
padding: 0;
|
||||
}
|
||||
.demo-cards h3 {
|
||||
font-size: 1em;
|
||||
}
|
||||
.demo-updates .mdl-card__title {
|
||||
min-height: 200px;
|
||||
background-image: url('https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTSIsmpJQm0OTBcGyY-Y3ECq4UMpN2lAcagoQ&usqp=CAU');
|
||||
background-position: 90% 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.demo-cards .mdl-card__actions a {
|
||||
color: #00BCD4;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.demo-options h3 {
|
||||
margin: 0;
|
||||
}
|
||||
.demo-options .mdl-checkbox__box-outline {
|
||||
border-color: rgba(255, 255, 255, 0.89);
|
||||
}
|
||||
.demo-options ul {
|
||||
margin: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
.demo-options li {
|
||||
margin: 4px 0;
|
||||
}
|
||||
.demo-options .material-icons {
|
||||
color: rgba(255, 255, 255, 0.89);
|
||||
}
|
||||
.demo-options .mdl-card__actions {
|
||||
height: 64px;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
-webkit-align-items: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
body {
|
||||
margin-bottom: 60px;
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.auth {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.auth-cont {
|
||||
padding: 1em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.auth-btn {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.auth-btn * {
|
||||
width: 100%;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.main {
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
dialog {
|
||||
position: absolute;
|
||||
top: 30%;
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
.mdl-list__item-avatar {
|
||||
background-color: #00000000 !important;
|
||||
color: black !important;
|
||||
}
|
||||
|
||||
header.demo-drawer-header {
|
||||
height: min-content !important;
|
||||
}
|
Loading…
Reference in New Issue
Block a user