repository migration
@@ -0,0 +1,165 @@
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using WhiteLagoon.Application.Common.Interfaces;
|
||||
using WhiteLagoon.Application.Common.Utility;
|
||||
using WhiteLagoon.Domain.Entities;
|
||||
using WhiteLagoon.Web.ViewModels;
|
||||
|
||||
namespace WhiteLagoon.Web.Controllers
|
||||
{
|
||||
public class AccountController : Controller
|
||||
{
|
||||
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
private readonly RoleManager<IdentityRole> _roleManager;
|
||||
|
||||
public AccountController(
|
||||
UserManager<ApplicationUser> userManager,
|
||||
RoleManager<IdentityRole> roleManager,
|
||||
SignInManager<ApplicationUser> signInManager)
|
||||
{
|
||||
_roleManager = roleManager;
|
||||
_userManager = userManager;
|
||||
_signInManager = signInManager;
|
||||
}
|
||||
|
||||
public IActionResult Login(string returnUrl=null)
|
||||
{
|
||||
|
||||
returnUrl??= Url.Content("~/");
|
||||
|
||||
LoginVM loginVM = new ()
|
||||
{
|
||||
RedirectUrl = returnUrl
|
||||
};
|
||||
|
||||
return View(loginVM);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Logout()
|
||||
{
|
||||
await _signInManager.SignOutAsync();
|
||||
return RedirectToAction("Index", "Home");
|
||||
}
|
||||
|
||||
public IActionResult AccessDenied()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
public IActionResult Register(string returnUrl = null)
|
||||
{
|
||||
returnUrl ??= Url.Content("~/");
|
||||
if (!_roleManager.RoleExistsAsync(SD.Role_Admin).GetAwaiter().GetResult())
|
||||
{
|
||||
_roleManager.CreateAsync(new IdentityRole(SD.Role_Admin)).Wait();
|
||||
_roleManager.CreateAsync(new IdentityRole(SD.Role_Customer)).Wait();
|
||||
}
|
||||
|
||||
RegisterVM registerVM = new ()
|
||||
{
|
||||
RoleList = _roleManager.Roles.Select(x => new SelectListItem
|
||||
{
|
||||
Text = x.Name,
|
||||
Value = x.Name
|
||||
}),
|
||||
RedirectUrl = returnUrl
|
||||
};
|
||||
|
||||
return View(registerVM);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Register(RegisterVM registerVM)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
ApplicationUser user = new()
|
||||
{
|
||||
Name = registerVM.Name,
|
||||
Email = registerVM.Email,
|
||||
PhoneNumber = registerVM.PhoneNumber,
|
||||
NormalizedEmail = registerVM.Email.ToUpper(),
|
||||
EmailConfirmed = true,
|
||||
UserName = registerVM.Email,
|
||||
CreatedAt = DateTime.Now
|
||||
};
|
||||
|
||||
var result = await _userManager.CreateAsync(user, registerVM.Password);
|
||||
|
||||
if (result.Succeeded)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(registerVM.Role))
|
||||
{
|
||||
await _userManager.AddToRoleAsync(user, registerVM.Role);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _userManager.AddToRoleAsync(user, SD.Role_Customer);
|
||||
}
|
||||
|
||||
await _signInManager.SignInAsync(user, isPersistent: false);
|
||||
if (string.IsNullOrEmpty(registerVM.RedirectUrl))
|
||||
{
|
||||
return RedirectToAction("Index", "Home");
|
||||
}
|
||||
else
|
||||
{
|
||||
return LocalRedirect(registerVM.RedirectUrl);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var error in result.Errors)
|
||||
{
|
||||
ModelState.AddModelError("", error.Description);
|
||||
}
|
||||
}
|
||||
registerVM.RoleList = _roleManager.Roles.Select(x => new SelectListItem
|
||||
{
|
||||
Text = x.Name,
|
||||
Value = x.Name
|
||||
});
|
||||
|
||||
return View(registerVM);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Login(LoginVM loginVM)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var result = await _signInManager
|
||||
.PasswordSignInAsync(loginVM.Email, loginVM.Password, loginVM.RememberMe, lockoutOnFailure:false);
|
||||
|
||||
|
||||
if (result.Succeeded)
|
||||
{
|
||||
var user = await _userManager.FindByEmailAsync(loginVM.Email);
|
||||
if (await _userManager.IsInRoleAsync(user, SD.Role_Admin))
|
||||
{
|
||||
return RedirectToAction("Index", "Dashboard");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(loginVM.RedirectUrl))
|
||||
{
|
||||
return RedirectToAction("Index", "Home");
|
||||
}
|
||||
else
|
||||
{
|
||||
return LocalRedirect(loginVM.RedirectUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ModelState.AddModelError("", "Invalid login attempt.");
|
||||
}
|
||||
}
|
||||
|
||||
return View(loginVM);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using WhiteLagoon.Application.Common.Interfaces;
|
||||
using WhiteLagoon.Application.Common.Utility;
|
||||
using WhiteLagoon.Application.Services.Interface;
|
||||
using WhiteLagoon.Domain.Entities;
|
||||
using WhiteLagoon.Infrastructure.Data;
|
||||
using WhiteLagoon.Web.ViewModels;
|
||||
|
||||
namespace WhiteLagoon.Web.Controllers
|
||||
{
|
||||
[Authorize(Roles = SD.Role_Admin)]
|
||||
public class AmenityController : Controller
|
||||
{
|
||||
private readonly IAmenityService _amenityService;
|
||||
private readonly IVillaService _villaService;
|
||||
|
||||
public AmenityController(IAmenityService amenityService, IVillaService villaService)
|
||||
{
|
||||
_amenityService = amenityService;
|
||||
_villaService = villaService;
|
||||
}
|
||||
|
||||
public IActionResult Index()
|
||||
{
|
||||
var amenities = _amenityService.GetAllAmenities();
|
||||
return View(amenities);
|
||||
}
|
||||
|
||||
public IActionResult Create()
|
||||
{
|
||||
AmenityVM amenityVM = new()
|
||||
{
|
||||
VillaList = _villaService.GetAllVillas().Select(u => new SelectListItem
|
||||
{
|
||||
Text = u.Name,
|
||||
Value = u.Id.ToString()
|
||||
})
|
||||
};
|
||||
return View(amenityVM);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Create(AmenityVM obj)
|
||||
{
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
_amenityService.CreateAmenity(obj.Amenity);
|
||||
TempData["success"] = "The amenity has been created successfully.";
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
obj.VillaList = _villaService.GetAllVillas().Select(u => new SelectListItem
|
||||
{
|
||||
Text = u.Name,
|
||||
Value = u.Id.ToString()
|
||||
});
|
||||
return View(obj);
|
||||
}
|
||||
|
||||
public IActionResult Update(int amenityId)
|
||||
{
|
||||
AmenityVM amenityVM = new()
|
||||
{
|
||||
VillaList = _villaService.GetAllVillas().Select(u => new SelectListItem
|
||||
{
|
||||
Text = u.Name,
|
||||
Value = u.Id.ToString()
|
||||
}),
|
||||
Amenity = _amenityService.GetAmenityById(amenityId)
|
||||
};
|
||||
if (amenityVM.Amenity == null)
|
||||
{
|
||||
return RedirectToAction("Error", "Home");
|
||||
}
|
||||
return View(amenityVM);
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Update(AmenityVM amenityVM)
|
||||
{
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
_amenityService.UpdateAmenity(amenityVM.Amenity);
|
||||
TempData["success"] = "The amenity has been updated successfully.";
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
amenityVM.VillaList = _villaService.GetAllVillas().Select(u => new SelectListItem
|
||||
{
|
||||
Text = u.Name,
|
||||
Value = u.Id.ToString()
|
||||
});
|
||||
return View(amenityVM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public IActionResult Delete(int amenityId)
|
||||
{
|
||||
AmenityVM amenityVM = new()
|
||||
{
|
||||
VillaList = _villaService.GetAllVillas().Select(u => new SelectListItem
|
||||
{
|
||||
Text = u.Name,
|
||||
Value = u.Id.ToString()
|
||||
}),
|
||||
Amenity = _amenityService.GetAmenityById(amenityId)
|
||||
};
|
||||
if (amenityVM.Amenity == null)
|
||||
{
|
||||
return RedirectToAction("Error", "Home");
|
||||
}
|
||||
return View(amenityVM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Delete(AmenityVM amenityVM)
|
||||
{
|
||||
Amenity? objFromDb = _amenityService.GetAmenityById(amenityVM.Amenity.Id);
|
||||
if (objFromDb is not null)
|
||||
{
|
||||
_amenityService.DeleteAmenity(objFromDb.Id);
|
||||
TempData["success"] = "The amenity has been deleted successfully.";
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
TempData["error"] = "The amenity could not be deleted.";
|
||||
return View();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,362 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Stripe;
|
||||
using Stripe.Checkout;
|
||||
using Syncfusion.DocIO;
|
||||
using Syncfusion.DocIO.DLS;
|
||||
using Syncfusion.DocIORenderer;
|
||||
using Syncfusion.Drawing;
|
||||
using Syncfusion.Pdf;
|
||||
using System.Security.Claims;
|
||||
using WhiteLagoon.Application.Common.Interfaces;
|
||||
using WhiteLagoon.Application.Common.Utility;
|
||||
using WhiteLagoon.Application.Contract;
|
||||
using WhiteLagoon.Application.Services.Interface;
|
||||
using WhiteLagoon.Domain.Entities;
|
||||
using WhiteLagoon.Infrastructure.Repository;
|
||||
|
||||
namespace WhiteLagoon.Web.Controllers
|
||||
{
|
||||
public class BookingController : Controller
|
||||
{
|
||||
private readonly IBookingService _bookingService;
|
||||
private readonly IWebHostEnvironment _webHostEnvironment;
|
||||
private readonly IVillaService _villaService;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly IVillaNumberService _villaNumberService;
|
||||
private readonly IPaymentService _paymentService;
|
||||
private readonly IEmailService _emailService;
|
||||
public BookingController(IBookingService bookingService,
|
||||
IPaymentService paymentService,
|
||||
IVillaService villaService, IVillaNumberService villaNumberService,
|
||||
IWebHostEnvironment webHostEnvironment, UserManager<ApplicationUser> userManager,
|
||||
IEmailService emailService)
|
||||
{
|
||||
_emailService = emailService;
|
||||
_paymentService = paymentService;
|
||||
_userManager = userManager;
|
||||
_villaService = villaService;
|
||||
_villaNumberService = villaNumberService;
|
||||
_bookingService = bookingService;
|
||||
_webHostEnvironment = webHostEnvironment;
|
||||
}
|
||||
[Authorize]
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
public IActionResult FinalizeBooking(int villaId, DateOnly checkInDate, int nights)
|
||||
{
|
||||
var claimsIdentity = (ClaimsIdentity)User.Identity;
|
||||
var userId = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier).Value;
|
||||
|
||||
ApplicationUser user = _userManager.FindByIdAsync(userId).GetAwaiter().GetResult();
|
||||
|
||||
Booking booking = new()
|
||||
{
|
||||
VillaId = villaId,
|
||||
Villa = _villaService.GetVillaById(villaId),
|
||||
CheckInDate = checkInDate,
|
||||
Nights = nights,
|
||||
CheckOutDate = checkInDate.AddDays(nights),
|
||||
UserId = userId,
|
||||
Phone=user.PhoneNumber,
|
||||
Email=user.Email,
|
||||
Name=user.Name
|
||||
};
|
||||
booking.TotalCost = booking.Villa.Price * nights;
|
||||
return View(booking);
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
[HttpPost]
|
||||
public IActionResult FinalizeBooking(Booking booking)
|
||||
{
|
||||
var villa = _villaService.GetVillaById(booking.VillaId);
|
||||
booking.TotalCost = villa.Price * booking.Nights;
|
||||
|
||||
booking.Status=SD.StatusPending;
|
||||
booking.BookingDate = DateTime.Now;
|
||||
|
||||
|
||||
|
||||
if (!_villaService.IsVillaAvailableByDate(villa.Id,booking.Nights,booking.CheckInDate))
|
||||
{
|
||||
TempData["error"] = "Room has been sold out!";
|
||||
//no rooms available
|
||||
return RedirectToAction(nameof(FinalizeBooking), new
|
||||
{
|
||||
villaId = booking.VillaId,
|
||||
checkInDate = booking.CheckInDate,
|
||||
nights = booking.Nights
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
_bookingService.CreateBooking(booking);
|
||||
|
||||
var domain = Request.Scheme+"://"+Request.Host.Value+"/";
|
||||
|
||||
var options = _paymentService.CreateStripeSessionOptions(booking, villa, domain);
|
||||
|
||||
var session = _paymentService.CreateStripeSession(options);
|
||||
|
||||
_bookingService.UpdateStripePaymentID(booking.Id, session.Id, session.PaymentIntentId);
|
||||
Response.Headers.Add("Location", session.Url);
|
||||
return new StatusCodeResult(303);
|
||||
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
public IActionResult BookingConfirmation(int bookingId)
|
||||
{
|
||||
Booking bookingFromDb = _bookingService.GetBookingById(bookingId);
|
||||
|
||||
if (bookingFromDb.Status == SD.StatusPending)
|
||||
{
|
||||
//this is a pending order, we need to confirm if payment was successful
|
||||
|
||||
var service = new SessionService();
|
||||
Session session = service.Get(bookingFromDb.StripeSessionId);
|
||||
|
||||
if (session.PaymentStatus == "paid")
|
||||
{
|
||||
_bookingService.UpdateStatus(bookingFromDb.Id, SD.StatusApproved,0);
|
||||
_bookingService.UpdateStripePaymentID(bookingFromDb.Id,session.Id,session.PaymentIntentId);
|
||||
|
||||
_emailService.SendEmailAsync(bookingFromDb.Email,"Booking Confirmation - White Lagoon", "<p>Your booking has been confirmed. Booking ID - " + bookingFromDb.Id+"</p>");
|
||||
}
|
||||
}
|
||||
|
||||
return View(bookingId);
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
public IActionResult BookingDetails(int bookingId)
|
||||
{
|
||||
Booking bookingFromDb = _bookingService.GetBookingById(bookingId);
|
||||
|
||||
if (bookingFromDb.VillaNumber==0 && bookingFromDb.Status == SD.StatusApproved)
|
||||
{
|
||||
var availableVillaNumber = AssignAvailableVillaNumberByVilla(bookingFromDb.VillaId);
|
||||
|
||||
bookingFromDb.VillaNumbers = _villaNumberService.GetAllVillaNumbers().Where(u => u.VillaId == bookingFromDb.VillaId
|
||||
&& availableVillaNumber.Any(x => x == u.Villa_Number)).ToList();
|
||||
}
|
||||
|
||||
return View(bookingFromDb);
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
[Authorize]
|
||||
public IActionResult GenerateInvoice(int id, string downloadType)
|
||||
{
|
||||
string basePath = _webHostEnvironment.WebRootPath;
|
||||
|
||||
WordDocument document = new WordDocument();
|
||||
|
||||
|
||||
// Load the template.
|
||||
string dataPath = basePath + @"/exports/BookingDetails.docx";
|
||||
using FileStream fileStream = new (dataPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
document.Open(fileStream, FormatType.Automatic);
|
||||
|
||||
//Update Template
|
||||
Booking bookingFromDb = _bookingService.GetBookingById(id);
|
||||
|
||||
TextSelection textSelection = document.Find("xx_customer_name", false, true);
|
||||
WTextRange textRange = textSelection.GetAsOneRange();
|
||||
textRange.Text = bookingFromDb.Name;
|
||||
|
||||
textSelection = document.Find("xx_customer_phone", false, true);
|
||||
textRange = textSelection.GetAsOneRange();
|
||||
textRange.Text = bookingFromDb.Phone;
|
||||
|
||||
textSelection = document.Find("xx_customer_email", false, true);
|
||||
textRange = textSelection.GetAsOneRange();
|
||||
textRange.Text = bookingFromDb.Email;
|
||||
|
||||
textSelection = document.Find("XX_BOOKING_NUMBER", false, true);
|
||||
textRange = textSelection.GetAsOneRange();
|
||||
textRange.Text = "BOOKING ID - " + bookingFromDb.Id;
|
||||
textSelection = document.Find("XX_BOOKING_DATE", false, true);
|
||||
textRange = textSelection.GetAsOneRange();
|
||||
textRange.Text = "BOOKING DATE - " + bookingFromDb.BookingDate.ToShortDateString();
|
||||
|
||||
|
||||
textSelection = document.Find("xx_payment_date", false, true);
|
||||
textRange = textSelection.GetAsOneRange();
|
||||
textRange.Text = bookingFromDb.PaymentDate.ToShortDateString();
|
||||
textSelection = document.Find("xx_checkin_date", false, true);
|
||||
textRange = textSelection.GetAsOneRange();
|
||||
textRange.Text = bookingFromDb.CheckInDate.ToShortDateString();
|
||||
textSelection = document.Find("xx_checkout_date", false, true);
|
||||
textRange = textSelection.GetAsOneRange();
|
||||
textRange.Text = bookingFromDb.CheckOutDate.ToShortDateString(); ;
|
||||
textSelection = document.Find("xx_booking_total", false, true);
|
||||
textRange = textSelection.GetAsOneRange();
|
||||
textRange.Text = bookingFromDb.TotalCost.ToString("c");
|
||||
|
||||
WTable table = new(document);
|
||||
|
||||
table.TableFormat.Borders.LineWidth = 1f;
|
||||
table.TableFormat.Borders.Color = Color.Black;
|
||||
table.TableFormat.Paddings.Top = 7f;
|
||||
table.TableFormat.Paddings.Bottom = 7f;
|
||||
table.TableFormat.Borders.Horizontal.LineWidth = 1f;
|
||||
|
||||
int rows = bookingFromDb.VillaNumber > 0 ? 3 : 2;
|
||||
table.ResetCells(rows, 4);
|
||||
|
||||
WTableRow row0 = table.Rows[0];
|
||||
|
||||
row0.Cells[0].AddParagraph().AppendText("NIGHTS");
|
||||
row0.Cells[0].Width=80;
|
||||
row0.Cells[1].AddParagraph().AppendText("VILLA");
|
||||
row0.Cells[1].Width = 220;
|
||||
row0.Cells[2].AddParagraph().AppendText("PRICE PER NIGHT");
|
||||
row0.Cells[3].AddParagraph().AppendText("TOTAL");
|
||||
row0.Cells[3].Width = 80;
|
||||
|
||||
WTableRow row1 = table.Rows[1];
|
||||
|
||||
row1.Cells[0].AddParagraph().AppendText(bookingFromDb.Nights.ToString());
|
||||
row1.Cells[0].Width = 80;
|
||||
row1.Cells[1].AddParagraph().AppendText(bookingFromDb.Villa.Name);
|
||||
row1.Cells[1].Width = 220;
|
||||
row1.Cells[2].AddParagraph().AppendText((bookingFromDb.TotalCost/bookingFromDb.Nights).ToString("c"));
|
||||
row1.Cells[3].AddParagraph().AppendText(bookingFromDb.TotalCost.ToString("c"));
|
||||
row1.Cells[3].Width = 80;
|
||||
|
||||
if (bookingFromDb.VillaNumber > 0)
|
||||
{
|
||||
WTableRow row2 = table.Rows[2];
|
||||
|
||||
row2.Cells[0].Width = 80;
|
||||
row2.Cells[1].AddParagraph().AppendText("Villa Number - " + bookingFromDb.VillaNumber.ToString());
|
||||
row2.Cells[1].Width = 220;
|
||||
row2.Cells[3].Width = 80;
|
||||
}
|
||||
|
||||
WTableStyle tableStyle = document.AddTableStyle("CustomStyle") as WTableStyle;
|
||||
tableStyle.TableProperties.RowStripe = 1;
|
||||
tableStyle.TableProperties.ColumnStripe = 2;
|
||||
tableStyle.TableProperties.Paddings.Top = 2;
|
||||
tableStyle.TableProperties.Paddings.Bottom = 1;
|
||||
tableStyle.TableProperties.Paddings.Left = 5.4f;
|
||||
tableStyle.TableProperties.Paddings.Right = 5.4f;
|
||||
|
||||
ConditionalFormattingStyle firstRowStyle = tableStyle.ConditionalFormattingStyles.Add(ConditionalFormattingType.FirstRow);
|
||||
firstRowStyle.CharacterFormat.Bold = true;
|
||||
firstRowStyle.CharacterFormat.TextColor = Color.FromArgb(255, 255, 255, 255);
|
||||
firstRowStyle.CellProperties.BackColor = Color.Black;
|
||||
|
||||
table.ApplyStyle("CustomStyle");
|
||||
|
||||
TextBodyPart bodyPart = new(document);
|
||||
bodyPart.BodyItems.Add(table);
|
||||
|
||||
document.Replace("<ADDTABLEHERE>", bodyPart, false, false);
|
||||
|
||||
|
||||
using DocIORenderer renderer = new ();
|
||||
MemoryStream stream = new();
|
||||
if (downloadType == "word")
|
||||
{
|
||||
|
||||
document.Save(stream, FormatType.Docx);
|
||||
stream.Position = 0;
|
||||
|
||||
return File(stream, "application/docx", "BookingDetails.docx");
|
||||
}
|
||||
else
|
||||
{
|
||||
PdfDocument pdfDocument = renderer.ConvertToPDF(document);
|
||||
pdfDocument.Save(stream);
|
||||
stream.Position = 0;
|
||||
|
||||
return File(stream, "application/pdf", "BookingDetails.pdf");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Roles = SD.Role_Admin)]
|
||||
public IActionResult CheckIn(Booking booking)
|
||||
{
|
||||
_bookingService.UpdateStatus(booking.Id, SD.StatusCheckedIn, booking.VillaNumber);
|
||||
TempData["Success"] = "Booking Updated Successfully.";
|
||||
return RedirectToAction(nameof(BookingDetails), new { bookingId = booking.Id });
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Roles = SD.Role_Admin)]
|
||||
public IActionResult CheckOut(Booking booking)
|
||||
{
|
||||
_bookingService.UpdateStatus(booking.Id, SD.StatusCompleted , booking.VillaNumber);
|
||||
TempData["Success"] = "Booking Completed Successfully.";
|
||||
return RedirectToAction(nameof(BookingDetails), new { bookingId = booking.Id });
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Roles = SD.Role_Admin)]
|
||||
public IActionResult CancelBooking(Booking booking)
|
||||
{
|
||||
_bookingService.UpdateStatus(booking.Id, SD.StatusCancelled, 0);
|
||||
TempData["Success"] = "Booking Cancelled Successfully.";
|
||||
return RedirectToAction(nameof(BookingDetails), new { bookingId = booking.Id });
|
||||
}
|
||||
|
||||
|
||||
private List<int> AssignAvailableVillaNumberByVilla(int villaId)
|
||||
{
|
||||
List<int> availableVillaNumbers = new();
|
||||
|
||||
var villaNumbers = _villaNumberService.GetAllVillaNumbers().Where(u => u.VillaId == villaId);
|
||||
|
||||
var checkedInVilla = _bookingService.GetCheckedInVillaNumbers(villaId);
|
||||
|
||||
foreach(var villaNumber in villaNumbers)
|
||||
{
|
||||
if (!checkedInVilla.Contains(villaNumber.Villa_Number))
|
||||
{
|
||||
availableVillaNumbers.Add(villaNumber.Villa_Number);
|
||||
}
|
||||
}
|
||||
return availableVillaNumbers;
|
||||
}
|
||||
|
||||
|
||||
#region API Calls
|
||||
[HttpGet]
|
||||
[Authorize]
|
||||
public IActionResult GetAll(string status)
|
||||
{
|
||||
IEnumerable<Booking> objBookings;
|
||||
string userId = "";
|
||||
if (string.IsNullOrEmpty(status))
|
||||
{
|
||||
status = "";
|
||||
}
|
||||
|
||||
if (!User.IsInRole(SD.Role_Admin))
|
||||
{
|
||||
var claimsIdentity = (ClaimsIdentity)User.Identity;
|
||||
userId = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier).Value;
|
||||
}
|
||||
|
||||
objBookings = _bookingService.GetAllBookings(userId, status);
|
||||
|
||||
return Json(new { data = objBookings });
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Stripe;
|
||||
using WhiteLagoon.Application.Common.Interfaces;
|
||||
using WhiteLagoon.Application.Common.Utility;
|
||||
using WhiteLagoon.Application.Services.Interface;
|
||||
using WhiteLagoon.Web.ViewModels;
|
||||
|
||||
namespace WhiteLagoon.Web.Controllers
|
||||
{
|
||||
public class DashboardController : Controller
|
||||
{
|
||||
private readonly IDashboardService _dashboardService;
|
||||
|
||||
public DashboardController(IDashboardService dashboardService)
|
||||
{
|
||||
_dashboardService = dashboardService;
|
||||
}
|
||||
|
||||
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
|
||||
public async Task<IActionResult> GetTotalBookingRadialChartData()
|
||||
{
|
||||
return Json(await _dashboardService.GetTotalBookingRadialChartData());
|
||||
}
|
||||
|
||||
public async Task<IActionResult> GetRegisteredUserChartData()
|
||||
{
|
||||
return Json(await _dashboardService.GetRegisteredUserChartData());
|
||||
}
|
||||
|
||||
public async Task<IActionResult> GetRevenueChartData()
|
||||
{
|
||||
return Json(await _dashboardService.GetRevenueChartData());
|
||||
}
|
||||
|
||||
public async Task<IActionResult> GetBookingPieChartData()
|
||||
{
|
||||
return Json(await _dashboardService.GetBookingPieChartData());
|
||||
}
|
||||
|
||||
public async Task<IActionResult> GetMemberAndBookingLineChartData()
|
||||
{
|
||||
return Json(await _dashboardService.GetMemberAndBookingLineChartData());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Syncfusion.Presentation;
|
||||
using WhiteLagoon.Application.Common.Interfaces;
|
||||
using WhiteLagoon.Application.Common.Utility;
|
||||
using WhiteLagoon.Application.Services.Interface;
|
||||
using WhiteLagoon.Web.ViewModels;
|
||||
|
||||
namespace WhiteLagoon.Web.Controllers
|
||||
{
|
||||
public class HomeController : Controller
|
||||
{
|
||||
|
||||
private readonly IVillaService _villaService;
|
||||
private readonly IWebHostEnvironment _webHostEnvironment;
|
||||
|
||||
public HomeController(IVillaService villaService, IWebHostEnvironment webHostEnvironment)
|
||||
{
|
||||
_villaService = villaService;
|
||||
_webHostEnvironment = webHostEnvironment;
|
||||
}
|
||||
|
||||
public IActionResult Index()
|
||||
{
|
||||
HomeVM homeVM = new()
|
||||
{
|
||||
VillaList = _villaService.GetAllVillas(),
|
||||
Nights=1,
|
||||
CheckInDate =DateOnly.FromDateTime(DateTime.Now),
|
||||
};
|
||||
return View(homeVM);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult GetVillasByDate(int nights, DateOnly checkInDate)
|
||||
{
|
||||
|
||||
HomeVM homeVM = new()
|
||||
{
|
||||
CheckInDate = checkInDate,
|
||||
VillaList = _villaService.GetVillasAvailabilityByDate(nights,checkInDate),
|
||||
Nights = nights
|
||||
};
|
||||
|
||||
return PartialView("_VillaList",homeVM);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult GeneratePPTExport(int id)
|
||||
{
|
||||
var villa = _villaService.GetVillaById(id);
|
||||
if (villa is null)
|
||||
{
|
||||
return RedirectToAction(nameof(Error));
|
||||
}
|
||||
|
||||
string basePath = _webHostEnvironment.WebRootPath;
|
||||
string filePath = basePath + @"/Exports/ExportVillaDetails.pptx";
|
||||
|
||||
|
||||
using IPresentation presentation = Presentation.Open(filePath);
|
||||
|
||||
ISlide slide = presentation.Slides[0];
|
||||
|
||||
|
||||
IShape? shape = slide.Shapes.FirstOrDefault(u=>u.ShapeName== "txtVillaName") as IShape;
|
||||
if(shape is not null)
|
||||
{
|
||||
shape.TextBody.Text = villa.Name;
|
||||
}
|
||||
|
||||
shape = slide.Shapes.FirstOrDefault(u => u.ShapeName == "txtVillaDescription") as IShape;
|
||||
if (shape is not null)
|
||||
{
|
||||
shape.TextBody.Text = villa.Description;
|
||||
}
|
||||
|
||||
|
||||
shape = slide.Shapes.FirstOrDefault(u => u.ShapeName == "txtOccupancy") as IShape;
|
||||
if (shape is not null)
|
||||
{
|
||||
shape.TextBody.Text = string.Format("Max Occupancy : {0} adults", villa.Occupancy);
|
||||
}
|
||||
shape = slide.Shapes.FirstOrDefault(u => u.ShapeName == "txtVillaSize") as IShape;
|
||||
if (shape is not null)
|
||||
{
|
||||
shape.TextBody.Text = string.Format("Villa Size: {0} sqft", villa.Sqft);
|
||||
}
|
||||
shape = slide.Shapes.FirstOrDefault(u => u.ShapeName == "txtPricePerNight") as IShape;
|
||||
if (shape is not null)
|
||||
{
|
||||
shape.TextBody.Text = string.Format("USD {0}/night", villa.Price.ToString("C"));
|
||||
}
|
||||
|
||||
|
||||
shape = slide.Shapes.FirstOrDefault(u => u.ShapeName == "txtVillaAmenitiesHeading") as IShape;
|
||||
if(shape is not null)
|
||||
{
|
||||
List<string> listItems = villa.VillaAmenity.Select(x => x.Name).ToList();
|
||||
|
||||
shape.TextBody.Text = "";
|
||||
|
||||
foreach (var item in listItems)
|
||||
{
|
||||
IParagraph paragraph = shape.TextBody.AddParagraph();
|
||||
ITextPart textPart = paragraph.AddTextPart(item);
|
||||
|
||||
paragraph.ListFormat.Type = ListType.Bulleted;
|
||||
paragraph.ListFormat.BulletCharacter = '\u2022';
|
||||
textPart.Font.FontName = "system-ui";
|
||||
textPart.Font.FontSize = 18;
|
||||
textPart.Font.Color = ColorObject.FromArgb(144, 148, 152);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
shape = slide.Shapes.FirstOrDefault(u => u.ShapeName == "imgVilla") as IShape;
|
||||
if(shape is not null)
|
||||
{
|
||||
byte[] imageData;
|
||||
string imageUrl;
|
||||
try
|
||||
{
|
||||
imageUrl= string.Format("{0}{1}", basePath, villa.ImageUrl);
|
||||
imageData = System.IO.File.ReadAllBytes(imageUrl);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
imageUrl = string.Format("{0}{1}", basePath, "/images/placeholder.png");
|
||||
imageData = System.IO.File.ReadAllBytes(imageUrl);
|
||||
}
|
||||
slide.Shapes.Remove(shape);
|
||||
using MemoryStream imageStream = new(imageData);
|
||||
IPicture newPicture = slide.Pictures.AddPicture(imageStream, 60,120,300,200);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
MemoryStream memoryStream = new();
|
||||
presentation.Save(memoryStream);
|
||||
memoryStream.Position = 0;
|
||||
return File(memoryStream,"application/pptx","villa.pptx");
|
||||
|
||||
|
||||
}
|
||||
|
||||
public IActionResult Privacy()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
public IActionResult Error()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using WhiteLagoon.Application.Common.Interfaces;
|
||||
using WhiteLagoon.Application.Services.Interface;
|
||||
using WhiteLagoon.Domain.Entities;
|
||||
using WhiteLagoon.Infrastructure.Data;
|
||||
|
||||
namespace WhiteLagoon.Web.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
public class VillaController : Controller
|
||||
{
|
||||
private readonly IVillaService _villaService;
|
||||
|
||||
public VillaController(IVillaService villaService)
|
||||
{
|
||||
_villaService = villaService;
|
||||
}
|
||||
|
||||
public IActionResult Index()
|
||||
{
|
||||
var villas = _villaService.GetAllVillas();
|
||||
return View(villas);
|
||||
}
|
||||
|
||||
public IActionResult Create()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Create(Villa obj)
|
||||
{
|
||||
|
||||
if (obj.Name == obj.Description)
|
||||
{
|
||||
ModelState.AddModelError("name", "The description cannot exactly match the Name.");
|
||||
}
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
|
||||
_villaService.CreateVilla(obj);
|
||||
TempData["success"] = "The villa has been created successfully.";
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View();
|
||||
}
|
||||
|
||||
public IActionResult Update(int villaId)
|
||||
{
|
||||
Villa? obj = _villaService.GetVillaById(villaId);
|
||||
if (obj == null)
|
||||
{
|
||||
return RedirectToAction("Error", "Home");
|
||||
}
|
||||
return View(obj);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Update(Villa obj)
|
||||
{
|
||||
if (ModelState.IsValid && obj.Id > 0)
|
||||
{
|
||||
|
||||
_villaService.UpdateVilla(obj);
|
||||
TempData["success"] = "The villa has been updated successfully.";
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
return View();
|
||||
}
|
||||
|
||||
public IActionResult Delete(int villaId)
|
||||
{
|
||||
Villa? obj = _villaService.GetVillaById(villaId);
|
||||
if (obj is null)
|
||||
{
|
||||
return RedirectToAction("Error", "Home");
|
||||
}
|
||||
return View(obj);
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Delete(Villa obj)
|
||||
{
|
||||
bool deleted = _villaService.DeleteVilla(obj.Id);
|
||||
if (deleted)
|
||||
{
|
||||
TempData["success"] = "The villa has been deleted successfully.";
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
else
|
||||
{
|
||||
TempData["error"] = "Failed to delete the villa.";
|
||||
}
|
||||
return View();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using WhiteLagoon.Application.Common.Interfaces;
|
||||
using WhiteLagoon.Application.Services.Interface;
|
||||
using WhiteLagoon.Domain.Entities;
|
||||
using WhiteLagoon.Infrastructure.Data;
|
||||
using WhiteLagoon.Web.ViewModels;
|
||||
|
||||
namespace WhiteLagoon.Web.Controllers
|
||||
{
|
||||
|
||||
public class VillaNumberController : Controller
|
||||
{
|
||||
private readonly IVillaNumberService _villaNumberService;
|
||||
private readonly IVillaService _villaService;
|
||||
public VillaNumberController(IVillaNumberService villaNumberService, IVillaService villaService)
|
||||
{
|
||||
_villaService = villaService;
|
||||
_villaNumberService = villaNumberService;
|
||||
}
|
||||
|
||||
public IActionResult Index()
|
||||
{
|
||||
var villaNumbers = _villaNumberService.GetAllVillaNumbers();
|
||||
return View(villaNumbers);
|
||||
}
|
||||
|
||||
public IActionResult Create()
|
||||
{
|
||||
VillaNumberVM villaNumberVM = new()
|
||||
{
|
||||
VillaList = _villaService.GetAllVillas().Select(u => new SelectListItem
|
||||
{
|
||||
Text = u.Name,
|
||||
Value = u.Id.ToString()
|
||||
})
|
||||
};
|
||||
return View(villaNumberVM);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Create(VillaNumberVM obj)
|
||||
{
|
||||
//ModelState.Remove("Villa");
|
||||
|
||||
bool roomNumberExists = _villaNumberService.CheckVillaNumberExists(obj.VillaNumber.Villa_Number);
|
||||
|
||||
if (ModelState.IsValid && !roomNumberExists)
|
||||
{
|
||||
_villaNumberService.CreateVillaNumber(obj.VillaNumber);
|
||||
TempData["success"] = "The villa Number has been created successfully.";
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
if (roomNumberExists)
|
||||
{
|
||||
TempData["error"] = "The villa Number already exists.";
|
||||
}
|
||||
obj.VillaList = _villaService.GetAllVillas().Select(u => new SelectListItem
|
||||
{
|
||||
Text = u.Name,
|
||||
Value = u.Id.ToString()
|
||||
});
|
||||
return View(obj);
|
||||
}
|
||||
|
||||
public IActionResult Update(int villaNumberId)
|
||||
{
|
||||
VillaNumberVM villaNumberVM = new()
|
||||
{
|
||||
VillaList = _villaService.GetAllVillas().Select(u => new SelectListItem
|
||||
{
|
||||
Text = u.Name,
|
||||
Value = u.Id.ToString()
|
||||
}),
|
||||
VillaNumber = _villaNumberService.GetVillaNumberById(villaNumberId)
|
||||
};
|
||||
if (villaNumberVM.VillaNumber == null)
|
||||
{
|
||||
return RedirectToAction("Error", "Home");
|
||||
}
|
||||
return View(villaNumberVM);
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Update(VillaNumberVM villaNumberVM)
|
||||
{
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
_villaNumberService.UpdateVillaNumber(villaNumberVM.VillaNumber);
|
||||
TempData["success"] = "The villa Number has been updated successfully.";
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
villaNumberVM.VillaList = _villaService.GetAllVillas().Select(u => new SelectListItem
|
||||
{
|
||||
Text = u.Name,
|
||||
Value = u.Id.ToString()
|
||||
});
|
||||
return View(villaNumberVM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public IActionResult Delete(int villaNumberId)
|
||||
{
|
||||
VillaNumberVM villaNumberVM = new()
|
||||
{
|
||||
VillaList = _villaService.GetAllVillas().Select(u => new SelectListItem
|
||||
{
|
||||
Text = u.Name,
|
||||
Value = u.Id.ToString()
|
||||
}),
|
||||
VillaNumber = _villaNumberService.GetVillaNumberById(villaNumberId)
|
||||
};
|
||||
if (villaNumberVM.VillaNumber == null)
|
||||
{
|
||||
return RedirectToAction("Error", "Home");
|
||||
}
|
||||
return View(villaNumberVM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Delete(VillaNumberVM villaNumberVM)
|
||||
{
|
||||
VillaNumber? objFromDb = _villaNumberService.GetVillaNumberById(villaNumberVM.VillaNumber.Villa_Number);
|
||||
if (objFromDb is not null)
|
||||
{
|
||||
_villaNumberService.DeleteVillaNumber(objFromDb.Villa_Number);
|
||||
TempData["success"] = "The villa number has been deleted successfully.";
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
TempData["error"] = "The villa number could not be deleted.";
|
||||
return View();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace WhiteLagoon.Web.Models
|
||||
{
|
||||
public class ErrorViewModel
|
||||
{
|
||||
public string? RequestId { get; set; }
|
||||
|
||||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Stripe;
|
||||
using Syncfusion.Licensing;
|
||||
using WhiteLagoon.Application.Common.Interfaces;
|
||||
using WhiteLagoon.Application.Contract;
|
||||
using WhiteLagoon.Application.Services.Implementation;
|
||||
using WhiteLagoon.Application.Services.Interface;
|
||||
using WhiteLagoon.Domain.Entities;
|
||||
using WhiteLagoon.Infrastructure.Data;
|
||||
using WhiteLagoon.Infrastructure.Emails;
|
||||
using WhiteLagoon.Infrastructure.Repository;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddControllersWithViews();
|
||||
builder.Services.AddDbContext<ApplicationDbContext>(option =>
|
||||
option.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
|
||||
|
||||
builder.Services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||
.AddEntityFrameworkStores<ApplicationDbContext>();
|
||||
|
||||
builder.Services.ConfigureApplicationCookie(option =>
|
||||
{
|
||||
option.AccessDeniedPath = "/Account/AccessDenied";
|
||||
option.LoginPath = "/Account/Login";
|
||||
});
|
||||
|
||||
builder.Services.Configure<IdentityOptions>(option =>
|
||||
{
|
||||
option.Password.RequiredLength = 6;
|
||||
});
|
||||
|
||||
builder.Services.AddScoped<IUnitOfWork,UnitOfWork>();
|
||||
builder.Services.AddScoped<IDashboardService, DashboardService>();
|
||||
builder.Services.AddScoped<IDbInitializer, DbInitializer>();
|
||||
|
||||
builder.Services.AddScoped<IVillaService, VillaService>();
|
||||
builder.Services.AddScoped<IVillaNumberService, VillaNumberService>();
|
||||
builder.Services.AddScoped<IAmenityService, AmenityService>();
|
||||
builder.Services.AddScoped<IBookingService, BookingService>();
|
||||
builder.Services.AddScoped<IPaymentService, PaymentService>();
|
||||
builder.Services.AddScoped<IEmailService, EmailService>();
|
||||
var app = builder.Build();
|
||||
StripeConfiguration.ApiKey=builder.Configuration.GetSection("Stripe:SecretKey").Get<string>();
|
||||
|
||||
SyncfusionLicenseProvider.RegisterLicense(builder.Configuration.GetSection("Syncfusion:Licensekey").Get<string>());
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
app.UseStaticFiles();
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseAuthorization();
|
||||
SeedDatabase();
|
||||
app.MapControllerRoute(
|
||||
name: "default",
|
||||
pattern: "{controller=Home}/{action=Index}/{id?}");
|
||||
|
||||
app.Run();
|
||||
void SeedDatabase()
|
||||
{
|
||||
using (var scope = app.Services.CreateScope())
|
||||
{
|
||||
var dbInitializer = scope.ServiceProvider.GetRequiredService<IDbInitializer>();
|
||||
dbInitializer.Initialize();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:46078",
|
||||
"sslPort": 44385
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:5137",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:7254;http://localhost:5137",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using WhiteLagoon.Domain.Entities;
|
||||
|
||||
namespace WhiteLagoon.Web.ViewModels
|
||||
{
|
||||
public class AmenityVM
|
||||
{
|
||||
public Amenity? Amenity { get; set; }
|
||||
[ValidateNever]
|
||||
public IEnumerable<SelectListItem>? VillaList { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using WhiteLagoon.Domain.Entities;
|
||||
|
||||
namespace WhiteLagoon.Web.ViewModels
|
||||
{
|
||||
public class HomeVM
|
||||
{
|
||||
public IEnumerable<Villa>? VillaList { get; set; }
|
||||
public DateOnly CheckInDate { get; set; }
|
||||
public DateOnly? CheckOutDate { get; set; }
|
||||
public int Nights { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace WhiteLagoon.Web.ViewModels
|
||||
{
|
||||
public class LoginVM
|
||||
{
|
||||
[Required]
|
||||
public string Email { get; set; }
|
||||
|
||||
[Required]
|
||||
[DataType(DataType.Password)]
|
||||
public string Password { get; set; }
|
||||
|
||||
public bool RememberMe { get; set; }
|
||||
|
||||
public string? RedirectUrl { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace WhiteLagoon.Web.ViewModels
|
||||
{
|
||||
public class RegisterVM
|
||||
{
|
||||
[Required]
|
||||
public string Email { get; set; }
|
||||
|
||||
[Required]
|
||||
[DataType(DataType.Password)]
|
||||
public string Password { get; set; }
|
||||
|
||||
[Required]
|
||||
[DataType(DataType.Password)]
|
||||
[Compare(nameof(Password))]
|
||||
[Display(Name = "Confirm password")]
|
||||
public string ConfirmPassword { get; set; }
|
||||
|
||||
[Required]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Display(Name="Phone Number")]
|
||||
public string? PhoneNumber { get; set; }
|
||||
|
||||
public string? RedirectUrl { get; set; }
|
||||
public string? Role { get; set; }
|
||||
[ValidateNever]
|
||||
public IEnumerable<SelectListItem>? RoleList { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using WhiteLagoon.Domain.Entities;
|
||||
|
||||
namespace WhiteLagoon.Web.ViewModels
|
||||
{
|
||||
public class VillaNumberVM
|
||||
{
|
||||
public VillaNumber? VillaNumber { get; set; }
|
||||
[ValidateNever]
|
||||
public IEnumerable<SelectListItem>? VillaList { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<div class="container pt-2">
|
||||
<img src="~/images/accessDenied.jpg" width="100%"/>
|
||||
</div>
|
||||
@@ -0,0 +1,58 @@
|
||||
@model LoginVM
|
||||
|
||||
<div class="container pt-5">
|
||||
<div class="card shadow border">
|
||||
<div class="card-header bg-success bg-gradient ml-0 py-4">
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
<h2 class="py-2 text-white">Login</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-4">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<section>
|
||||
<form method="post">
|
||||
<input asp-for="RedirectUrl" hidden />
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger" ></div>
|
||||
<div class="form-floating mb-3">
|
||||
<input asp-for="Email" class="form-control" aria-required="true" />
|
||||
<label asp-for="Email" class="form-label"></label>
|
||||
<span asp-validation-for="Email" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating mb-3">
|
||||
<input asp-for="Password" class="form-control" aria-required="true" />
|
||||
<label asp-for="Password" class="form-label"></label>
|
||||
<span asp-validation-for="Password" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="checkbox mb-3">
|
||||
<input class="form-check-input" asp-for="RememberMe" />
|
||||
|
||||
<label class="form-label">
|
||||
Remember Me
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" class="w-100 btn btn-lg btn-outline-success">Log in</button>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between pt-2">
|
||||
<p>
|
||||
<a asp-action="ForgotPassword">Forgot your password?</a>
|
||||
</p>
|
||||
<p>
|
||||
<a asp-action="Register" asp-route-returnUrl="@Model.RedirectUrl">Register as a new user</a>
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
<partial name="_ValidationScriptsPartial" />
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
@model RegisterVM
|
||||
|
||||
<div class="container pt-5">
|
||||
<div class="card shadow border ">
|
||||
<div class="card-header bg-success bg-gradient ml-0 py-4">
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
<h2 class="py-2 text-white">Register</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-4">
|
||||
<div class="row pt-3">
|
||||
<div class="col-md-12">
|
||||
<form class="row" method="post">
|
||||
<input asp-for="RedirectUrl" hidden />
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<div class="form-floating mb-3 col-md-12">
|
||||
<input asp-for="Email" class="form-control" aria-required="true" />
|
||||
<label asp-for="Email" class="ms-2 text-muted"></label>
|
||||
<span asp-validation-for="Email" class="text-danger"/>
|
||||
</div>
|
||||
<div class="form-floating mb-3 col-md-6">
|
||||
<input asp-for="Name" class="form-control" />
|
||||
<label asp-for="Name" class="ms-2 text-muted"></label>
|
||||
<span asp-validation-for="Name" class="text-danger" />
|
||||
</div>
|
||||
<div class="form-floating mb-3 col-md-6">
|
||||
<input asp-for="PhoneNumber" class="form-control" />
|
||||
<label asp-for="PhoneNumber" class="ms-2 text-muted"></label>
|
||||
<span asp-validation-for="PhoneNumber" class="text-danger" />
|
||||
</div>
|
||||
<div class="form-floating mb-3 col-md-6">
|
||||
<input asp-for="Password" class="form-control" />
|
||||
<label asp-for="Password" class="ms-2 text-muted"></label>
|
||||
<span asp-validation-for="Password" class="text-danger" />
|
||||
</div>
|
||||
<div class="form-floating mb-3 col-md-6">
|
||||
<input asp-for="ConfirmPassword" class="form-control" />
|
||||
<label asp-for="ConfirmPassword" class="ms-2 text-muted">Confirm Password</label>
|
||||
<span asp-validation-for="ConfirmPassword" class="text-danger" />
|
||||
</div>
|
||||
|
||||
<div class="form-floating mb-3 col-md-6">
|
||||
<select asp-for="Role" asp-items="@Model.RoleList" class="form-select">
|
||||
<option disabled selected>-Select Role-</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<button type="submit" class="w-100 btn btn-lg btn-outline-success">Register</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
<partial name="_ValidationScriptsPartial" />
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
@model AmenityVM
|
||||
|
||||
<div class="w-100 card border-0 p-4">
|
||||
<div class="card-header bg-success bg-gradient ml-0 py-3">
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
<h2 class="text-white py-2">Create Amenity</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body border p-4">
|
||||
<form method="post" class="row">
|
||||
<div class="p-3">
|
||||
@* <div asp-validation-summary="All"></div> *@
|
||||
<div class="form-floating py-1 col-12">
|
||||
<select asp-for="@Model.Amenity.VillaId" asp-items="@Model.VillaList"
|
||||
class="form-select border shadow">
|
||||
<option disabled selected>--Select Villa--</option>
|
||||
</select>
|
||||
<label asp-for="Amenity.VillaId" class="ms-2"></label>
|
||||
<span asp-validation-for="Amenity.VillaId" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Amenity.Name" class="form-control border shadow" />
|
||||
<label asp-for="Amenity.Name" class="ms-2"></label>
|
||||
<span asp-validation-for="Amenity.Name" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Amenity.Description" class="form-control border shadow" />
|
||||
<label asp-for="Amenity.Description" class="ms-2"></label>
|
||||
<span asp-validation-for="Amenity.Description" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="row pt-2">
|
||||
<div class="col-6 col-md-3">
|
||||
<button type="submit" class="btn btn-success w-100">
|
||||
<i class="bi bi-check-circle"></i> Create
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-6 col-md-3">
|
||||
<a asp-controller="Amenity" asp-action="Index" class="btn btn-secondary w-100">
|
||||
<i class="bi bi-x-circle"></i> Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts{
|
||||
@{
|
||||
<partial name="_ValidationScriptsPartial" />
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
@model AmenityVM
|
||||
|
||||
<div class="w-100 card border-0 p-4">
|
||||
<div class="card-header bg-success bg-gradient ml-0 py-3">
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
<h2 class="text-white py-2">Update Amenity</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body border p-4">
|
||||
<form method="post" class="row">
|
||||
<input hidden asp-for="Amenity.Id" />
|
||||
<div class="p-3">
|
||||
@* <div asp-validation-summary="All"></div> *@
|
||||
<div class="form-floating py-1 col-12">
|
||||
<select asp-for="@Model.Amenity.VillaId" disabled asp-items="@Model.VillaList"
|
||||
class="form-select border shadow">
|
||||
<option disabled selected>--Select Villa--</option>
|
||||
</select>
|
||||
<label asp-for="Amenity.VillaId" class="ms-2"></label>
|
||||
<span asp-validation-for="Amenity.VillaId" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Amenity.Name" readonly class="form-control border shadow" />
|
||||
<label asp-for="Amenity.Name" class="ms-2"></label>
|
||||
<span asp-validation-for="Amenity.Name" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Amenity.Description" readonly class="form-control border shadow" />
|
||||
<label asp-for="Amenity.Description" class="ms-2"></label>
|
||||
<span asp-validation-for="Amenity.Description" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="row pt-2">
|
||||
<div class="col-6 col-md-3">
|
||||
<button type="submit" class="btn btn-danger w-100">
|
||||
<i class="bi bi-check-circle"></i> Delete
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-6 col-md-3">
|
||||
<a asp-controller="Amenity" asp-action="Index" class="btn btn-secondary w-100">
|
||||
<i class="bi bi-x-circle"></i> Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts{
|
||||
@{
|
||||
<partial name="_ValidationScriptsPartial" />
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
@model IEnumerable<Amenity>
|
||||
|
||||
<div class="w-100 card border-0 p-4">
|
||||
<div class="card-header bg-success bg-gradient ml-0 py-3">
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
<h2 class="text-white py-2">Amenity List</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body border p-4">
|
||||
<div class="row pb-3">
|
||||
<div class="col-6 offset-6 text-end">
|
||||
<a asp-controller="Amenity" asp-action="Create" class="btn btn-secondary">
|
||||
<i class="bi bi-plus-circle"></i> Create New Amenity
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
Id
|
||||
</th>
|
||||
<th>Name</th>
|
||||
<th>Villa Name</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var obj in Model)
|
||||
{
|
||||
<tr>
|
||||
<td>@obj.Id</td>
|
||||
<td>@obj.Name</td>
|
||||
<td>@obj.Villa.Name</td>
|
||||
<td>
|
||||
<div class="w-75 btn-group" role="group">
|
||||
<a asp-controller="Amenity" asp-action="Update" asp-route-amenityId="@obj.Id"
|
||||
class="btn btn-success mx-2">
|
||||
<i class="bi bi-pencil-square"></i> Edit
|
||||
</a>
|
||||
<a asp-controller="Amenity" asp-action="Delete" asp-route-amenityId="@obj.Id"
|
||||
class="btn btn-danger mx-2">
|
||||
<i class="bi bi-trash-fill"></i> Delete
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,56 @@
|
||||
@model AmenityVM
|
||||
|
||||
<div class="w-100 card border-0 p-4">
|
||||
<div class="card-header bg-success bg-gradient ml-0 py-3">
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
<h2 class="text-white py-2">Update Amenity</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body border p-4">
|
||||
<form method="post" class="row">
|
||||
<input hidden asp-for="Amenity.Id" />
|
||||
<div class="p-3">
|
||||
@* <div asp-validation-summary="All"></div> *@
|
||||
<div class="form-floating py-1 col-12">
|
||||
<select asp-for="@Model.Amenity.VillaId" asp-items="@Model.VillaList"
|
||||
class="form-select border shadow">
|
||||
<option disabled selected>--Select Villa--</option>
|
||||
</select>
|
||||
<label asp-for="Amenity.VillaId" class="ms-2"></label>
|
||||
<span asp-validation-for="Amenity.VillaId" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Amenity.Name" class="form-control border shadow" />
|
||||
<label asp-for="Amenity.Name" class="ms-2"></label>
|
||||
<span asp-validation-for="Amenity.Name" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Amenity.Description" class="form-control border shadow" />
|
||||
<label asp-for="Amenity.Description" class="ms-2"></label>
|
||||
<span asp-validation-for="Amenity.Description" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="row pt-2">
|
||||
<div class="col-6 col-md-3">
|
||||
<button type="submit" class="btn btn-success w-100">
|
||||
<i class="bi bi-check-circle"></i> Update
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-6 col-md-3">
|
||||
<a asp-controller="Amenity" asp-action="Index" class="btn btn-secondary w-100">
|
||||
<i class="bi bi-x-circle"></i> Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts{
|
||||
@{
|
||||
<partial name="_ValidationScriptsPartial" />
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
@model int
|
||||
|
||||
<div class="container pt-4">
|
||||
<div class="col-12 text-center">
|
||||
<h1 class="text-success text-center">Your Vacation is Confirmed!</h1>
|
||||
Your Order Number is : @Model <br />
|
||||
<p>You can view all order details in Manage Order Section.</p>
|
||||
<img src="~/images/orderConfirmed.jpg" style="border-radius:20px" width="65%" />
|
||||
</div>
|
||||
<div class="col-12 text-center text-warning">
|
||||
<p class="pt-1">Pack your bags! You are one step closer to an amazing vacation!</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,185 @@
|
||||
@model Booking
|
||||
|
||||
<div class="p-4 mt-0 mt-lg-4">
|
||||
<div class="row" style="border: 1px solid #aaa;">
|
||||
|
||||
<div class="col-12 col-lg-6 p-4 2 mt-2 mt-md-0">
|
||||
<div class="row p-1 " style="border-radius:20px; ">
|
||||
<div class="col-6">
|
||||
<h3 class="text-success">Villa Details</h3>
|
||||
</div>
|
||||
<div class="col-6 text-end">
|
||||
<a class="btn btn-secondary my-2"
|
||||
asp-controller="Booking" asp-action="Index"
|
||||
><i class="bi bi-arrow-left-circle"></i> Back to Bookings</a>
|
||||
</div>
|
||||
<hr />
|
||||
<partial name="_VillaDetail" model="@Model.Villa"/>
|
||||
<hr />
|
||||
<div class="text-end">
|
||||
<h4 class="text-danger font-weight-bold ">
|
||||
Booking Total :
|
||||
<span style="border-bottom:1px solid #ff6a00">
|
||||
@Model.TotalCost.ToString("c")
|
||||
</span>
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
<form method="post">
|
||||
<div class="row pt-1 mb-3 " style="border-radius:20px; ">
|
||||
<div class="col-12 text-center">
|
||||
|
||||
<button asp-action="GenerateInvoice" asp-route-id="@Model.Id"
|
||||
asp-route-downloadType="word" type="submit"
|
||||
class="btn btn-sm btn-secondary my-1">
|
||||
<i class="bi bi-file-earmark-word"></i> Generate Invoice (word)
|
||||
</button>
|
||||
|
||||
<button asp-action="GenerateInvoice" asp-route-id="@Model.Id"
|
||||
asp-route-downloadType="pdf" type="submit"
|
||||
class="btn btn-sm btn-secondary my-1">
|
||||
<i class="bi bi-file-earmark-pdf"></i> Generate Invoice (pdf)
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-6 p-4 2 mt-4 mt-md-0" style="border-left:1px solid #aaa">
|
||||
<form method="post">
|
||||
<input asp-for="Id" hidden />
|
||||
<input asp-for="VillaId" hidden />
|
||||
<input asp-for="UserId" hidden />
|
||||
<input asp-for="CheckInDate" hidden />
|
||||
|
||||
<input asp-for="CheckOutDate" hidden />
|
||||
<input asp-for="Nights" hidden />
|
||||
<div class="row pt-1 mb-3 " style="border-radius:20px; ">
|
||||
<div class="col-6">
|
||||
<h3 class="text-success">Enter Booking Details</h3>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
@if ((Model.Status == SD.StatusApproved || Model.Status == SD.StatusPending)
|
||||
&& User.IsInRole(SD.Role_Admin))
|
||||
{
|
||||
<button type="submit" asp-controller="Booking" asp-action="CancelBooking" class="btn btn-sm btn-outline-danger form-control my-1">
|
||||
<i class="bi bi-x-circle"></i> Cancel Booking
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="form-group pt-2 col-6">
|
||||
<label class="text-warning">Name</label>
|
||||
<input asp-for="Name" class="form-control" />
|
||||
</div>
|
||||
<div class="form-group pt-2 col-6">
|
||||
<label class="text-warning">Phone</label>
|
||||
<input asp-for="Phone" class="form-control" />
|
||||
</div>
|
||||
<div class="form-group pt-2 col-6">
|
||||
<label class="text-warning">Email</label>
|
||||
<input asp-for="Email" class="form-control" />
|
||||
</div>
|
||||
|
||||
<div class="form-group pt-2 col-6">
|
||||
<label class="text-warning">No. of nights</label>
|
||||
<input asp-for="Nights" disabled class="form-control" />
|
||||
</div>
|
||||
<div class="form-group pt-2 col-6">
|
||||
<label class="text-warning">Status</label>
|
||||
<input asp-for="Status" disabled class="form-control" />
|
||||
</div>
|
||||
<div class="form-group pt-2 col-6">
|
||||
<label class="text-warning">Booking Date</label>
|
||||
<input asp-for="BookingDate" disabled class="form-control" />
|
||||
</div>
|
||||
<div class="form-group pt-2 col-6">
|
||||
<label class="text-warning">Check-in Date</label>
|
||||
<input asp-for="CheckInDate" disabled class="form-control" />
|
||||
</div>
|
||||
<div class="form-group pt-2 col-6">
|
||||
<label class="text-warning">Actual Check-in Date</label>
|
||||
<input asp-for="ActualCheckInDate" disabled class="form-control" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group pt-2 col-6">
|
||||
<label class="text-warning">Check-out Date</label>
|
||||
<input asp-for="CheckOutDate" disabled class="form-control" />
|
||||
</div>
|
||||
<div class="form-group pt-2 col-6">
|
||||
<label class="text-warning">Actual Check-out Date</label>
|
||||
<input asp-for="ActualCheckOutDate" disabled class="form-control" />
|
||||
</div>
|
||||
@if(Model.Status==SD.StatusApproved && User.IsInRole(SD.Role_Admin))
|
||||
{
|
||||
<div class="form-group pt-2 col-6">
|
||||
<label class="text-danger" asp-for="VillaNumber"></label>
|
||||
|
||||
<select class="form-select" asp-for="VillaNumber">
|
||||
@foreach (var item in Model.VillaNumbers)
|
||||
{
|
||||
<option value="@item.Villa_Number">@item.Villa_Number</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<input asp-for="VillaNumber" hidden />
|
||||
@if (Model.Status == SD.StatusCheckedIn || Model.Status == SD.StatusCompleted)
|
||||
{
|
||||
<div class="form-group pt-2 col-6">
|
||||
<label class="text-warning">Villa Number</label>
|
||||
<input asp-for="VillaNumber" disabled class="form-control" />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@if (Model.IsPaymentSuccessful && User.IsInRole(SD.Role_Admin))
|
||||
{
|
||||
<div class="form-group pt-2 col-6">
|
||||
<label class="text-warning">Stripe PaymentIntent Id</label>
|
||||
<input asp-for="StripePaymentIntentId" disabled class="form-control" />
|
||||
</div>
|
||||
<div class="form-group pt-2 col-6">
|
||||
<label class="text-warning">Stripe Session Id</label>
|
||||
<input asp-for="StripeSessionId" disabled class="form-control" />
|
||||
</div>
|
||||
<div class="form-group pt-2 col-6">
|
||||
<label class="text-warning">Payment Date</label>
|
||||
<input asp-for="PaymentDate" disabled class="form-control" />
|
||||
</div>
|
||||
}
|
||||
<div class="form-group pt-2 col-6">
|
||||
<label class="text-warning">Status</label>
|
||||
<input asp-for="Status" disabled class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group pt-2 pt-md-4">
|
||||
@if (User.IsInRole(SD.Role_Admin))
|
||||
{
|
||||
@if (Model.Status == SD.StatusApproved)
|
||||
{
|
||||
<button type="submit" asp-controller="Booking" asp-action="CheckIn"
|
||||
class="btn btn-warning form-control my-1">
|
||||
<i class="bi bi-check2-square"></i> Check In
|
||||
</button>
|
||||
}
|
||||
@if (Model.Status == SD.StatusCheckedIn)
|
||||
{
|
||||
<button type="submit" asp-controller="Booking" asp-action="CheckOut"
|
||||
class="btn btn-success form-control my-1">
|
||||
<i class="bi bi-clipboard2-check"></i> Check Out / Complete Booking
|
||||
</button>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,88 @@
|
||||
|
||||
@model Booking
|
||||
|
||||
<div class="container pt-4 mt-0 mt-lg-4">
|
||||
<div class="row" style="border: 1px solid #aaa;">
|
||||
|
||||
<div class="col-12 col-lg-7 p-4 2 mt-4 mt-md-0">
|
||||
<div class="row p-1 my-1 " style="border-radius:20px; ">
|
||||
<div class="col-6">
|
||||
<h3 class="text-success">Villa Details</h3>
|
||||
</div>
|
||||
<div class="text-end col-6 ">
|
||||
<a asp-controller="Home" asp-action="Index"
|
||||
class="btn btn-sm btn-outline-danger" style="width:200px;">
|
||||
<i class="bi bi-arrow-left-square"></i> Modify Selection
|
||||
</a>
|
||||
</div>
|
||||
<hr />
|
||||
<partial name="_VillaDetail" model="@Model.Villa" />
|
||||
<hr />
|
||||
<div class="text-end">
|
||||
<h4 class="text-danger font-weight-bold ">
|
||||
Booking Total :
|
||||
<span style="border-bottom:1px solid #ff6a00">
|
||||
@Model.TotalCost.ToString("c")
|
||||
</span>
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-5 p-4 2 mt-4 mt-md-0" style="border-left:1px solid #aaa">
|
||||
<form method="post">
|
||||
<input asp-for="VillaId" hidden />
|
||||
<input asp-for="UserId" hidden />
|
||||
<input asp-for="CheckInDate" hidden />
|
||||
<input asp-for="CheckOutDate" hidden />
|
||||
<input asp-for="Nights" hidden />
|
||||
<div class="row pt-1 mb-3 " style="border-radius:20px; ">
|
||||
<div class="col-12">
|
||||
<h3 class="text-success">Enter Booking Details</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group pt-0">
|
||||
<label asp-for="Name" class="text-warning">Name</label>
|
||||
<input asp-for="Name" class="form-control" />
|
||||
<span asp-validation-for="Name" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group pt-2">
|
||||
<label asp-for="Phone" class="text-warning">Phone</label>
|
||||
<input asp-for="Phone" class="form-control" />
|
||||
<span asp-validation-for="Phone" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group pt-2">
|
||||
<label asp-for="Email" class="text-warning">Email</label>
|
||||
<input asp-for="Email" class="form-control" />
|
||||
<span asp-validation-for="Email" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group pt-2">
|
||||
<label asp-for="CheckInDate" class="text-warning">Check in Date</label>
|
||||
<input asp-for="CheckInDate" disabled class="form-control" />
|
||||
</div>
|
||||
<div class="form-group pt-2">
|
||||
<label asp-for="CheckOutDate" class="text-warning">Check Out Date</label>
|
||||
<input asp-for="CheckOutDate" disabled class="form-control" />
|
||||
</div>
|
||||
<div class="form-group pt-2">
|
||||
<label asp-for="Nights" class="text-warning">No. of nights</label>
|
||||
<input asp-for="Nights" disabled class="form-control" />
|
||||
</div>
|
||||
<div class="form-group pt-2 pt-md-4">
|
||||
@if (Model.Villa.IsAvailable)
|
||||
{
|
||||
<button type="submit" class="btn btn-success form-control">Looks Good! Checkout Now</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<input class="btn btn-danger disabled form-control" value="Sold Out" />
|
||||
}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
<partial name="_ValidationScriptsPartial" />
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
|
||||
@{
|
||||
var status = Context.Request.Query["status"];
|
||||
|
||||
var approved = "";
|
||||
var pending = "";
|
||||
var checkedIn = "";
|
||||
var completed = "";
|
||||
var cancelled = "";
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case SD.StatusPending:
|
||||
pending = "text-white bg-success";
|
||||
break;
|
||||
case SD.StatusApproved:
|
||||
approved = "text-white bg-success";
|
||||
break;
|
||||
case SD.StatusCheckedIn:
|
||||
checkedIn = "text-white bg-success";
|
||||
break;
|
||||
case SD.StatusCompleted:
|
||||
completed = "text-white bg-success";
|
||||
break;
|
||||
case SD.StatusCancelled:
|
||||
cancelled = "text-white bg-success";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
<div class="w-100 card border-0 p-4">
|
||||
<div class="card-header bg-success bg-gradient ml-0 py-3">
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
<h2 class="text-white py-2">Booking List</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body border p-4">
|
||||
<div class="d-flex justify-content-end pb-4 pt-2">
|
||||
<ul class="list-group list-group-horizontal-sm">
|
||||
<a style="text-decoration:none;" asp-controller="Booking" asp-action="Index"
|
||||
asp-route-status="@SD.StatusPending">
|
||||
<li class="list-group-item @pending"> @SD.StatusPending </li>
|
||||
</a>
|
||||
<a style="text-decoration:none;" asp-controller="Booking" asp-action="Index"
|
||||
asp-route-status="@SD.StatusApproved">
|
||||
<li class="list-group-item @approved"> @SD.StatusApproved </li>
|
||||
</a>
|
||||
<a style="text-decoration:none;" asp-controller="Booking" asp-action="Index"
|
||||
asp-route-status="@SD.StatusCheckedIn">
|
||||
<li class="list-group-item @checkedIn"> @SD.StatusCheckedIn </li>
|
||||
</a>
|
||||
<a style="text-decoration:none;" asp-controller="Booking" asp-action="Index"
|
||||
asp-route-status="@SD.StatusCompleted">
|
||||
<li class="list-group-item @completed"> @SD.StatusCompleted </li>
|
||||
</a>
|
||||
<a style="text-decoration:none;" asp-controller="Booking" asp-action="Index"
|
||||
asp-route-status="@SD.StatusCancelled">
|
||||
<li class="list-group-item @cancelled"> @SD.StatusCancelled </li>
|
||||
</a>
|
||||
</ul>
|
||||
</div>
|
||||
<table id="tblBookings" class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Name</th>
|
||||
<th>Phone</th>
|
||||
<th>Email</th>
|
||||
<th>Status</th>
|
||||
<th>Check In Date</th>
|
||||
<th>Nights</th>
|
||||
<th>Total</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts{
|
||||
<script src="~/js/booking.js"></script>
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="page-title-box d-flex align-items-center justify-content-between">
|
||||
<h4 class="mb-0">Dashboard</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-xl-4 mt-2">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="float-end mt-2">
|
||||
<div id="totalBookingsRadialChart" data-colors='["--bs-success"]'></div>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-muted mb-0">Total Bookings</p>
|
||||
<h4 class="my-1">
|
||||
<span id="spanTotalBookingCount">XX</span>
|
||||
</h4>
|
||||
</div>
|
||||
<p class="text-muted mt-3 mb-0" id="sectionBookingCount"></p>
|
||||
|
||||
<div class="justify-content-center text-center chart-spinner" style="display:none">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-xl-4 mt-2">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="float-end mt-2">
|
||||
<div id="totalUserRadialChart" data-colors='["--bs-warning"]'></div>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-muted mb-0">Total Users</p>
|
||||
<h4 class="my-1">
|
||||
<span id="spanTotalUserCount">XX</span>
|
||||
</h4>
|
||||
</div>
|
||||
<p class="text-muted mt-3 mb-0" id="sectionUserCount"></p>
|
||||
|
||||
<div class="justify-content-center text-center chart-spinner" style="display:none">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-xl-4 mt-2">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="float-end mt-2">
|
||||
<div id="totalRevenueRadialChart" data-colors='["#F0006B"]'></div>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-muted mb-0">Total Revenue</p>
|
||||
<h4 class="my-1">
|
||||
<span id="spanTotalRevenueCount">XX</span>
|
||||
</h4>
|
||||
</div>
|
||||
<p class="text-muted mt-3 mb-0" id="sectionRevenueCount"></p>
|
||||
|
||||
<div class="justify-content-center text-center chart-spinner" style="display:none">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12 col-xl-8 mt-2">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div>
|
||||
<p class="text-muted mb-0">New Members And Bookings In Past 30 Days</p>
|
||||
</div>
|
||||
<div id="newMembersAndBookingsLineChart" data-colors='["--bs-warning","--bs-primary"]'>
|
||||
</div>
|
||||
<div class="justify-content-center text-center chart-spinner" style="display:none">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12 col-xl-4 mt-2">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="">
|
||||
<p class="text-muted mb-0">Customer Bookings</p>
|
||||
</div>
|
||||
<div id="customerBookingsPieChart" data-colors='["--bs-warning","--bs-primary"]'>
|
||||
</div>
|
||||
|
||||
<div class="justify-content-center text-center chart-spinner" style="display:none">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section scripts{
|
||||
<script src="~/js/dashboard/radailChart.js"></script>
|
||||
<script src="~/js/dashboard/getTotalBookingsRadial.js"></script>
|
||||
<script src="~/js/dashboard/getTotalRevenueRadial.js"></script>
|
||||
<script src="~/js/dashboard/getTotalUserRadial.js"></script>
|
||||
<script src="~/js/dashboard/getCustomerBookingPieChart.js"></script>
|
||||
<script src="~/js/dashboard/getCustomerAndBookingLineChart.js"></script>
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
@model HomeVM
|
||||
|
||||
<div>
|
||||
<div id="carouselExampleIndicators" class="carousel slide">
|
||||
<div class="carousel-indicators">
|
||||
<button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
|
||||
<button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="1" aria-label="Slide 2"></button>
|
||||
<button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="2" aria-label="Slide 3"></button>
|
||||
</div>
|
||||
<div class="carousel-inner">
|
||||
<div class="carousel-item active">
|
||||
<img src="~/images/slide2.jpg" class="d-block w-100" alt="...">
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<img src="~/images/slide1.jpg" class="d-block w-100" alt="...">
|
||||
</div>
|
||||
</div>
|
||||
<button class="carousel-control-prev" type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide="prev">
|
||||
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
|
||||
<span class="visually-hidden">Previous</span>
|
||||
</button>
|
||||
<button class="carousel-control-next" type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide="next">
|
||||
<span class="carousel-control-next-icon" aria-hidden="true"></span>
|
||||
<span class="visually-hidden">Next</span>
|
||||
</button>
|
||||
</div>
|
||||
<form method="post"
|
||||
asp-action="GetVillasByDate" >
|
||||
<div class="row p-0 mx-0 py-4">
|
||||
|
||||
<div class="col-12 col-md-5 offset-md-1 pl-2 pr-2 pr-md-0">
|
||||
<div class="form-group">
|
||||
<label>Check In Date</label>
|
||||
<input asp-for="CheckInDate" type="date" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-8 col-md-3 pl-2 pr-2">
|
||||
<div class="form-group">
|
||||
<label>No. of nights</label>
|
||||
<select class="form-select" asp-for="Nights">
|
||||
@for(var i = 1; i < 11; i++)
|
||||
{
|
||||
<option value="@i">@i</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-4 col-md-2 pt-4 pr-2">
|
||||
<div class="form-group">
|
||||
<button type="button" onclick="fnLoadVillaList()" class="btn btn-success btn-block">
|
||||
<i class="bi bi-search"></i> Check Availability
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<partial name="_VillaList" model="Model"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@section scripts{
|
||||
<script>
|
||||
function fnLoadVillaList() {
|
||||
$('.spinner').show();
|
||||
var objData = {
|
||||
checkInDate: $("#CheckInDate").val(),
|
||||
nights: $("#Nights").val()
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
data:objData,
|
||||
url: "@Url.Action("GetVillasByDate","Home")",
|
||||
success: function (data) {
|
||||
$("#VillasList").empty();
|
||||
$("#VillasList").html(data);
|
||||
$('.spinner').hide();
|
||||
},
|
||||
failure: function (response) {
|
||||
$('.spinner').hide();
|
||||
alert(response.responseText);
|
||||
},
|
||||
error: function (response) {
|
||||
$('.spinner').hide();
|
||||
alert(response.responseText);
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
@{
|
||||
ViewData["Title"] = "Privacy Policy";
|
||||
}
|
||||
<h1>@ViewData["Title"]</h1>
|
||||
|
||||
<p>Use this page to detail your site's privacy policy.</p>
|
||||
@@ -0,0 +1,3 @@
|
||||
<div class="container">
|
||||
<img src="~/images/notfound.jpg" width="100%" />
|
||||
</div>
|
||||
@@ -0,0 +1,79 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-bs-theme="dark">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>@ViewData["Title"] - WhiteLagoon.Web</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.1/css/bootstrap.min.css" integrity="sha512-Z/def5z5u2aR89OuzYcxmDJ0Bnd5V1cKqBEbvLOiUNWdg9PQeXVvXLI90SE4QOHGlfLqUnDNVAYyZi8UwUTmWQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href="~/WhiteLagoon.Web.styles.css" asp-append-version="true" />
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.css" integrity="sha512-3pIirOrwegjM6erE5gPSwkUzO+3cTjpnV9lexlNZqvupR64iZBnOOTiiLPb9M36zpMScbmUNIcHUqKD47M719g==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
<link rel="stylesheet" href="~/css/spinner.css"/>
|
||||
<link rel="stylesheet" href="//cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css" />
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light border-bottom box-shadow">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index"><img src="~/images/resort.png" style="width:35px"/></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" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" asp-controller="Booking" asp-action="Index">Manage Bookings</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<div class="p-2 border rounded">
|
||||
<div class="form-check form-switch" id="btnSwitch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="flexSwitchCheckDefault">
|
||||
<label class="form-check-label" for="flexSwitchCheckDefault">Mode</label>
|
||||
</div>
|
||||
</div>
|
||||
<partial name="_LoginPartial" />
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
<div class="">
|
||||
<main role="main">
|
||||
<div class="loading spinner" style="display:none;"></div>
|
||||
<partial name="_Notification" />
|
||||
@RenderBody()
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="border-top footer text-muted">
|
||||
<div class="container text-center">
|
||||
Made with <i class="bi bi-heart-fill"></i> by DotNetMastery
|
||||
</div>
|
||||
</footer>
|
||||
@* jquery-ajax-unobtrusive@3.2.6 *@
|
||||
<script type="text/javascript">
|
||||
document.getElementById('btnSwitch').addEventListener('click', () => {
|
||||
if (document.documentElement.getAttribute('data-bs-theme') == 'dark') {
|
||||
document.documentElement.setAttribute('data-bs-theme', 'light')
|
||||
}
|
||||
else {
|
||||
document.documentElement.setAttribute('data-bs-theme', 'dark')
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.0.1/js/bootstrap.bundle.min.js" integrity="sha512-sH8JPhKJUeA9PWk3eOcOl8U+lfZTgtBXD41q6cO/slwxGHCxKcW45K4oPCUhHG7NMB4mbKEddVmPuTXtpbCbFA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||
<script src="//cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js" asp-append-version="true"></script>
|
||||
@* <script src="~/js/jquery.unobtrusive-ajax.min.js"></script> *@
|
||||
|
||||
@await RenderSectionAsync("Scripts", required: false)
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,40 @@
|
||||
/* Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification
|
||||
for details on configuring this project to bundle and minify static web assets. */
|
||||
|
||||
|
||||
|
||||
.btn-primary {
|
||||
color: #fff;
|
||||
background-color: #1b6ec2;
|
||||
border-color: #1861ac;
|
||||
}
|
||||
|
||||
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
|
||||
color: #fff;
|
||||
background-color: #1b6ec2;
|
||||
border-color: #1861ac;
|
||||
}
|
||||
|
||||
.border-top {
|
||||
border-top: 1px solid #e5e5e5;
|
||||
}
|
||||
.border-bottom {
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.box-shadow {
|
||||
box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
|
||||
}
|
||||
|
||||
button.accept-policy {
|
||||
font-size: 1rem;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
line-height: 60px;
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-bs-theme="dark">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>@ViewData["Title"] - WhiteLagoon.Web</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.1/css/bootstrap.min.css" integrity="sha512-Z/def5z5u2aR89OuzYcxmDJ0Bnd5V1cKqBEbvLOiUNWdg9PQeXVvXLI90SE4QOHGlfLqUnDNVAYyZi8UwUTmWQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href="~/WhiteLagoon.Web.styles.css" asp-append-version="true" />
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.css" integrity="sha512-3pIirOrwegjM6erE5gPSwkUzO+3cTjpnV9lexlNZqvupR64iZBnOOTiiLPb9M36zpMScbmUNIcHUqKD47M719g==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
<link rel="stylesheet" href="~/css/spinner.css"/>
|
||||
<link rel="stylesheet" href="//cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css" />
|
||||
<link rel="stylesheet" href="~/css/apexcharts.css" />
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light border-bottom box-shadow">
|
||||
<div class="container-fluid d-flex justify-content-between">
|
||||
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index"><img src="~/images/resort.png" style="width:35px"/></a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu"
|
||||
aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
</div>
|
||||
<partial name="_LoginPartialAdmin" />
|
||||
</nav>
|
||||
</header>
|
||||
<div class="container-fluid">
|
||||
<div class="loading spinner" style="display:none;"></div>
|
||||
<div class="row">
|
||||
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-dark sidebar collapse">
|
||||
<div class="position-static pt-3">
|
||||
<ul class="navbar-nav">
|
||||
<li>
|
||||
<div class="text-muted small fw-bold text-uppercase px-3">
|
||||
Menu
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" asp-controller="Dashboard" asp-action="Index">
|
||||
<span class="me-2"><i class="bi bi-speedometer2"></i></span>
|
||||
<span>Dashboard</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<div class="text-muted small fw-bold text-uppercase px-3 mt-2">
|
||||
Content Management
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" asp-controller="Villa" asp-action="Index">
|
||||
<span class="me-2"><i class="bi bi-house-door"></i></span>
|
||||
<span>Villa</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" asp-controller="VillaNumber" asp-action="Index">
|
||||
<span class="me-2"><i class="bi bi-list-ol"></i></i></span>
|
||||
<span>VillaNumber</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" asp-controller="Amenity" asp-action="Index">
|
||||
<span class="me-2"><i class="bi bi-building"></i></span>
|
||||
<span>Amenity</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" asp-controller="Booking" asp-action="Index" asp-route-status="@SD.StatusApproved">
|
||||
<span class="me-2"><i class="bi bi-journal-plus"></i></span>
|
||||
<span>Booking</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 w-100">
|
||||
<partial name="_Notification" />
|
||||
@RenderBody()
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="border-top footer bg-dark text-muted">
|
||||
<div class="container text-center">
|
||||
Made with <i class="bi bi-heart-fill"></i> by DotNetMastery
|
||||
</div>
|
||||
</footer>
|
||||
@* jquery-ajax-unobtrusive@3.2.6 *@
|
||||
|
||||
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.0.1/js/bootstrap.bundle.min.js" integrity="sha512-sH8JPhKJUeA9PWk3eOcOl8U+lfZTgtBXD41q6cO/slwxGHCxKcW45K4oPCUhHG7NMB4mbKEddVmPuTXtpbCbFA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||
<script src="//cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js" asp-append-version="true"></script>
|
||||
@* <script src="~/js/jquery.unobtrusive-ajax.min.js"></script> *@
|
||||
<script src="~/js/apexcharts.js"></script>
|
||||
@await RenderSectionAsync("Scripts", required: false)
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,40 @@
|
||||
/* Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification
|
||||
for details on configuring this project to bundle and minify static web assets. */
|
||||
|
||||
|
||||
|
||||
.btn-primary {
|
||||
color: #fff;
|
||||
background-color: #1b6ec2;
|
||||
border-color: #1861ac;
|
||||
}
|
||||
|
||||
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
|
||||
color: #fff;
|
||||
background-color: #1b6ec2;
|
||||
border-color: #1861ac;
|
||||
}
|
||||
|
||||
.border-top {
|
||||
border-top: 1px solid #e5e5e5;
|
||||
}
|
||||
.border-bottom {
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.box-shadow {
|
||||
box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
|
||||
}
|
||||
|
||||
button.accept-policy {
|
||||
font-size: 1rem;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
line-height: 60px;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
@using Microsoft.AspNetCore.Identity
|
||||
|
||||
@inject SignInManager<ApplicationUser> SignInManager
|
||||
@inject UserManager<ApplicationUser> UserManager
|
||||
|
||||
|
||||
<ul class="navbar-nav">
|
||||
@if (SignInManager.IsSignedIn(User))
|
||||
{
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Hello @UserManager.GetUserName(User)</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" asp-controller="Account" asp-action="Logout">Logout</a>
|
||||
</li>
|
||||
}
|
||||
else
|
||||
{
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" asp-controller="Account" asp-action="Register">Register</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" asp-controller="Account" asp-action="Login">Login</a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
@@ -0,0 +1,17 @@
|
||||
@using Microsoft.AspNetCore.Identity
|
||||
|
||||
@inject SignInManager<ApplicationUser> SignInManager
|
||||
@inject UserManager<ApplicationUser> UserManager
|
||||
|
||||
|
||||
<ul class="navbar-nav d-none d-md-flex nav-login">
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
|
||||
data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Hello @UserManager.GetUserName(User)
|
||||
</a>
|
||||
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<a class="nav-link text-center" asp-controller="Account" asp-action="Logout">Logout</a>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -0,0 +1,16 @@
|
||||
@if (TempData["error"] != null)
|
||||
{
|
||||
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js" integrity="sha512-VEd+nq25CkR676O+pLBnDW09R7VQX9Mdiij052gVCp5yVH3jGtH70Ho/UUv4mJDsEdTvqRCFZg0NKGiojGnUCw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script type="text/javascript">
|
||||
toastr.error('@TempData["error"]');
|
||||
</script>
|
||||
}
|
||||
@if (TempData["success"] != null)
|
||||
{
|
||||
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js" integrity="sha512-VEd+nq25CkR676O+pLBnDW09R7VQX9Mdiij052gVCp5yVH3jGtH70Ho/UUv4mJDsEdTvqRCFZg0NKGiojGnUCw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script type="text/javascript">
|
||||
toastr.success('@TempData["success"]');
|
||||
</script>
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
|
||||
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
|
||||
@@ -0,0 +1,39 @@
|
||||
@model Villa
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-5">
|
||||
<img src="@Model.ImageUrl" style="border-radius:10px;" width="100%" />
|
||||
</div>
|
||||
<div class="col-12 col-md-7">
|
||||
<div class="row p-2">
|
||||
<div class="col-12">
|
||||
<p class="card-title text-warning" style="font-size:xx-large">@Model.Name</p>
|
||||
<p class="card-text" style="font-size:large">
|
||||
@Html.Raw(Model.Description)
|
||||
</p>
|
||||
@if (Model.VillaAmenity != null && Model.VillaAmenity.Count() > 0)
|
||||
{
|
||||
<p class="h5 text-white">Villa Amenities</p>
|
||||
<ul>
|
||||
@foreach (var amenity in Model.VillaAmenity)
|
||||
{
|
||||
<li>@amenity.Name</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row col-12">
|
||||
<span class="text-end p-0 pt-3 m-0">
|
||||
<span class="float-right">Max Occupancy : @Model.Occupancy adults </span><br />
|
||||
<span class="float-right pt-1">Villa Size : @Model.Sqft sqft</span><br />
|
||||
<p class="text-warning font-weight-bold pt-1">
|
||||
USD
|
||||
<span style=" #ff6a00">
|
||||
@Model.Price.ToString("c") / night
|
||||
</span>
|
||||
</p>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,89 @@
|
||||
@model HomeVM
|
||||
<div id="VillasList">
|
||||
<div class="row px-lg-5 m-lg-4 m-sm-0 px-sm-0" style="--bs-gutter-x:0">
|
||||
|
||||
@foreach (var villa in Model.VillaList)
|
||||
{
|
||||
|
||||
<div class="p-4 col-md-12 col-lg-6">
|
||||
<div class="row" style="border-radius:5px; border: 1px solid #aaa">
|
||||
<div class="col-4 p-2">
|
||||
<img class="d-block w-100" style="border-radius:5px;" src="@villa.ImageUrl">
|
||||
</div>
|
||||
<div class="col-8">
|
||||
<div class="d-flex justify-content-between">
|
||||
<p class="card-title text-warning" style="font-size:xx-large">@villa.Name</p>
|
||||
<div class="pt-2">
|
||||
<button type="button" class="btn btn-sm btn-outline-success" data-bs-toggle="modal" data-bs-target='#exampleModal-@(villa.Id)'>
|
||||
Details
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="card-text">
|
||||
@Html.Raw(villa.Description)
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="row pb-3 pt-2">
|
||||
<div class="col-4">
|
||||
@if (Model.CheckInDate > DateOnly.FromDateTime(DateTime.Now))
|
||||
{
|
||||
if (villa.IsAvailable)
|
||||
{
|
||||
<a asp-controller="Booking" asp-action="FinalizeBooking"
|
||||
asp-route-villaId="@villa.Id" asp-route-checkInDate="@Model.CheckInDate"
|
||||
asp-route-nights="@Model.Nights"
|
||||
class="btn btn-success form-control btn-block">
|
||||
Book
|
||||
</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<a class="btn btn-outline-danger disabled form-control btn-block">
|
||||
Sold Out
|
||||
</a>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<span class="">Max Occupancy : @villa.Occupancy adults </span><br />
|
||||
<span class=" pt-1">Villa Size : @villa.Sqft sqft</span><br />
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<span class="text-warning float-end font-weight-bold pt-1" style="font-size:25px;">
|
||||
USD
|
||||
<span style="border-bottom:1px solid #ff6a00">
|
||||
@villa.Price.ToString("c")
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="exampleModal-@(villa.Id)" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl" style="border: 1px solid #aaa; border-radius:7px;">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-3 text-success" id="exampleModalLabel">Villa Details</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body m-0">
|
||||
|
||||
<partial name="_VillaDetail" model="@villa" />
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button asp-controller="Home" asp-action="GeneratePPTExport"
|
||||
asp-route-id="@villa.Id" type="submit" class="btn btn-outline-warning">
|
||||
<i class="bi bi-file-earmark-ppt"></i> Download Villa PPT
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-danger" data-bs-dismiss="modal">Close</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,68 @@
|
||||
@model Villa
|
||||
|
||||
|
||||
<div class="w-100 card border-0 p-4">
|
||||
<div class="card-header bg-success bg-gradient ml-0 py-3">
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
<h2 class="text-white py-2">Create Villa</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body border p-4">
|
||||
<form method="post" class="row" enctype="multipart/form-data">
|
||||
<div class="p-3">
|
||||
@* <div asp-validation-summary="All"></div> *@
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Name" class="form-control border shadow" />
|
||||
<label asp-for="Name" class="ms-2"></label>
|
||||
<span asp-validation-for="Name" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Description" class="form-control border shadow" />
|
||||
<label asp-for="Description" class="ms-2"></label>
|
||||
<span asp-validation-for="Description" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Price" class="form-control border shadow" />
|
||||
<label asp-for="Price" class="ms-2"></label>
|
||||
<span asp-validation-for="Price" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Sqft" class="form-control border shadow" />
|
||||
<label asp-for="Sqft" class="ms-2"></label>
|
||||
<span asp-validation-for="Sqft" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Occupancy" class="form-control border shadow" />
|
||||
<label asp-for="Occupancy" class="ms-2"></label>
|
||||
<span asp-validation-for="Occupancy" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="ImageUrl" hidden class="form-control border shadow" />
|
||||
<input asp-for="Image" class="form-control border shadow" />
|
||||
<label asp-for="ImageUrl" class="ms-2 "></label>
|
||||
<span asp-validation-for="ImageUrl" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="row pt-2">
|
||||
<div class="col-6 col-md-3">
|
||||
<button type="submit" class="btn btn-success w-100">
|
||||
<i class="bi bi-check-circle"></i> Create
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-6 col-md-3">
|
||||
<a asp-controller="Villa" asp-action="Index" class="btn btn-secondary w-100">
|
||||
<i class="bi bi-x-circle"></i> Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts{
|
||||
@{
|
||||
<partial name="_ValidationScriptsPartial" />
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
@model Villa
|
||||
|
||||
<div class="w-100 card border-0 p-4">
|
||||
<div class="card-header bg-success bg-gradient ml-0 py-3">
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
<h2 class="text-white py-2">Delete Villa</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body border p-4">
|
||||
<form method="post" class="row">
|
||||
<input asp-for="Id" hidden />
|
||||
<div class="col-10">
|
||||
<div class="p-3">
|
||||
@* <div asp-validation-summary="All"></div> *@
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Name" disabled class="form-control border shadow" />
|
||||
<label asp-for="Name" class="ms-2"></label>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Description" disabled class="form-control border shadow" />
|
||||
<label asp-for="Description" class="ms-2"></label>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Price" disabled class="form-control border shadow" />
|
||||
<label asp-for="Price" class="ms-2"></label>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Sqft" disabled class="form-control border shadow" />
|
||||
<label asp-for="Sqft" class="ms-2"></label>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Occupancy" disabled class="form-control border shadow" />
|
||||
<label asp-for="Occupancy" class="ms-2"></label>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="ImageUrl" disabled class="form-control border shadow" />
|
||||
<label asp-for="ImageUrl" class="ms-2"></label>
|
||||
</div>
|
||||
<div class="row pt-2">
|
||||
<div class="col-6 col-md-3">
|
||||
<button type="submit" class="btn btn-danger w-100">
|
||||
<i class="bi bi-trash-fill"></i> Delete
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-6 col-md-3">
|
||||
<a asp-controller="Villa" asp-action="Index" class="btn btn-secondary w-100">
|
||||
<i class="bi bi-x-circle"></i> Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<img src="@Model.ImageUrl" width="100%"
|
||||
style="border-radius:5px; border:1px solid #bbb9b9" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts{
|
||||
@{
|
||||
<partial name="_ValidationScriptsPartial" />
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
@model IEnumerable<WhiteLagoon.Domain.Entities.Villa>
|
||||
|
||||
<div class="w-100 card border-0 p-4">
|
||||
<div class="card-header bg-success bg-gradient ml-0 py-3">
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
<h2 class="text-white py-2">Villa List</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body border p-4">
|
||||
<div class="row pb-3">
|
||||
<div class="col-6 offset-6 text-end">
|
||||
<a asp-controller="Villa" asp-action="Create" class="btn btn-secondary">
|
||||
<i class="bi bi-plus-circle"></i> Create New Villa
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
Name
|
||||
</th>
|
||||
<th>Price</th>
|
||||
<th>Sqft</th>
|
||||
<th>Occupancy</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var obj in Model)
|
||||
{
|
||||
<tr>
|
||||
<td>@obj.Name</td>
|
||||
<td>@obj.Price</td>
|
||||
<td>@obj.Sqft</td>
|
||||
<td>@obj.Occupancy</td>
|
||||
<td>
|
||||
<div class="w-75 btn-group" role="group">
|
||||
<a asp-controller="Villa" asp-action="Update" asp-route-villaId="@obj.Id"
|
||||
class="btn btn-success mx-2">
|
||||
<i class="bi bi-pencil-square"></i> Edit
|
||||
</a>
|
||||
<a asp-controller="Villa" asp-action="Delete" asp-route-villaId="@obj.Id"
|
||||
class="btn btn-danger mx-2">
|
||||
<i class="bi bi-trash-fill"></i> Delete
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,75 @@
|
||||
@model Villa
|
||||
|
||||
<div class="w-100 card border-0 p-4">
|
||||
<div class="card-header bg-success bg-gradient ml-0 py-3">
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
<h2 class="text-white py-2">Update Villa</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body border p-4">
|
||||
<form method="post" class="row" enctype="multipart/form-data">
|
||||
<input asp-for="Id" hidden />
|
||||
<div class="col-10">
|
||||
<div class="p-3">
|
||||
@* <div asp-validation-summary="All"></div> *@
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Name" class="form-control border shadow" />
|
||||
<label asp-for="Name" class="ms-2"></label>
|
||||
<span asp-validation-for="Name" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Description" class="form-control border shadow" />
|
||||
<label asp-for="Description" class="ms-2"></label>
|
||||
<span asp-validation-for="Description" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Price" class="form-control border shadow" />
|
||||
<label asp-for="Price" class="ms-2"></label>
|
||||
<span asp-validation-for="Price" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Sqft" class="form-control border shadow" />
|
||||
<label asp-for="Sqft" class="ms-2"></label>
|
||||
<span asp-validation-for="Sqft" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Occupancy" class="form-control border shadow" />
|
||||
<label asp-for="Occupancy" class="ms-2"></label>
|
||||
<span asp-validation-for="Occupancy" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="Image" class="form-control border shadow" />
|
||||
<input asp-for="ImageUrl" hidden class="form-control border shadow" />
|
||||
<label asp-for="ImageUrl" class="ms-2"></label>
|
||||
<span asp-validation-for="ImageUrl" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="row pt-2">
|
||||
<div class="col-6 col-md-3">
|
||||
<button type="submit" class="btn btn-success w-100">
|
||||
<i class="bi bi-check-circle"></i> Update
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-6 col-md-3">
|
||||
<a asp-controller="Villa" asp-action="Index" class="btn btn-secondary w-100">
|
||||
<i class="bi bi-x-circle"></i> Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<img src="@Model.ImageUrl" width="100%"
|
||||
style="border-radius:5px; border:1px solid #bbb9b9" />
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts{
|
||||
@{
|
||||
<partial name="_ValidationScriptsPartial" />
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
@model VillaNumberVM
|
||||
|
||||
<div class="w-100 card border-0 p-4">
|
||||
<div class="card-header bg-success bg-gradient ml-0 py-3">
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
<h2 class="text-white py-2">Create Villa Number</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body border p-4">
|
||||
<form method="post" class="row">
|
||||
<div class="p-3">
|
||||
@* <div asp-validation-summary="All"></div> *@
|
||||
<div class="form-floating py-1 col-12">
|
||||
<select asp-for="@Model.VillaNumber.VillaId" asp-items="@Model.VillaList"
|
||||
class="form-select border shadow">
|
||||
<option disabled selected>--Select Villa--</option>
|
||||
</select>
|
||||
<label asp-for="VillaNumber.VillaId" class="ms-2"></label>
|
||||
<span asp-validation-for="VillaNumber.VillaId" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="VillaNumber.Villa_Number" class="form-control border shadow" />
|
||||
<label asp-for="VillaNumber.Villa_Number" class="ms-2"></label>
|
||||
<span asp-validation-for="VillaNumber.Villa_Number" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="VillaNumber.SpecialDetails" class="form-control border shadow" />
|
||||
<label asp-for="VillaNumber.SpecialDetails" class="ms-2"></label>
|
||||
<span asp-validation-for="VillaNumber.SpecialDetails" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="row pt-2">
|
||||
<div class="col-6 col-md-3">
|
||||
<button type="submit" class="btn btn-success w-100">
|
||||
<i class="bi bi-check-circle"></i> Create
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-6 col-md-3">
|
||||
<a asp-controller="VillaNumber" asp-action="Index" class="btn btn-secondary w-100">
|
||||
<i class="bi bi-x-circle"></i> Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts{
|
||||
@{
|
||||
<partial name="_ValidationScriptsPartial" />
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
@model VillaNumberVM
|
||||
|
||||
<div class="w-100 card border-0 p-4">
|
||||
<div class="card-header bg-success bg-gradient ml-0 py-3">
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
<h2 class="text-white py-2">Update Villa Number</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body border p-4">
|
||||
<form method="post" class="row">
|
||||
<input asp-for="VillaNumber.Villa_Number" hidden />
|
||||
<div class="p-3">
|
||||
|
||||
<div class="form-floating py-1 col-12">
|
||||
<select disabled asp-for="@Model.VillaNumber.VillaId" asp-items="@Model.VillaList"
|
||||
class="form-select border shadow">
|
||||
<option disabled selected>--Select Villa--</option>
|
||||
</select>
|
||||
<label asp-for="VillaNumber.VillaId" class="ms-2"></label>
|
||||
<span asp-validation-for="VillaNumber.VillaId" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="VillaNumber.Villa_Number" disabled class="form-control border shadow" />
|
||||
<label asp-for="VillaNumber.Villa_Number" class="ms-2"></label>
|
||||
<span asp-validation-for="VillaNumber.Villa_Number" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="VillaNumber.SpecialDetails" disabled class="form-control border shadow" />
|
||||
<label asp-for="VillaNumber.SpecialDetails" class="ms-2"></label>
|
||||
<span asp-validation-for="VillaNumber.SpecialDetails" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="row pt-2">
|
||||
<div class="col-6 col-md-3">
|
||||
<button type="submit" class="btn btn-danger w-100">
|
||||
<i class="bi bi-check-circle"></i> Delete
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-6 col-md-3">
|
||||
<a asp-controller="VillaNumber" asp-action="Index" class="btn btn-secondary w-100">
|
||||
<i class="bi bi-x-circle"></i> Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts{
|
||||
@{
|
||||
<partial name="_ValidationScriptsPartial" />
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
@model IEnumerable<VillaNumber>
|
||||
|
||||
<div class="w-100 card border-0 p-4">
|
||||
<div class="card-header bg-success bg-gradient ml-0 py-3">
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
<h2 class="text-white py-2">Villa Number List</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body border p-4">
|
||||
<div class="row pb-3">
|
||||
<div class="col-6 offset-6 text-end">
|
||||
<a asp-controller="VillaNumber" asp-action="Create" class="btn btn-secondary">
|
||||
<i class="bi bi-plus-circle"></i> Create New Villa Number
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
Villa Name
|
||||
</th>
|
||||
<th>Villa Number</th>
|
||||
<th>Speical Details</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var obj in Model)
|
||||
{
|
||||
<tr>
|
||||
<td>@obj.Villa.Name</td>
|
||||
<td>@obj.Villa_Number</td>
|
||||
<td>@obj.SpecialDetails</td>
|
||||
<td>
|
||||
<div class="w-75 btn-group" role="group">
|
||||
<a asp-controller="VillaNumber" asp-action="Update" asp-route-villaNumberId="@obj.Villa_Number"
|
||||
class="btn btn-success mx-2">
|
||||
<i class="bi bi-pencil-square"></i> Edit
|
||||
</a>
|
||||
<a asp-controller="VillaNumber" asp-action="Delete" asp-route-villaNumberId="@obj.Villa_Number"
|
||||
class="btn btn-danger mx-2">
|
||||
<i class="bi bi-trash-fill"></i> Delete
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,55 @@
|
||||
@model VillaNumberVM
|
||||
|
||||
<div class="w-100 card border-0 p-4">
|
||||
<div class="card-header bg-success bg-gradient ml-0 py-3">
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
<h2 class="text-white py-2">Update Villa Number</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body border p-4">
|
||||
<form method="post" class="row">
|
||||
<input asp-for="VillaNumber.Villa_Number" hidden />
|
||||
<div class="p-3">
|
||||
|
||||
<div class="form-floating py-1 col-12">
|
||||
<select asp-for="@Model.VillaNumber.VillaId" asp-items="@Model.VillaList"
|
||||
class="form-select border shadow">
|
||||
<option disabled selected>--Select Villa--</option>
|
||||
</select>
|
||||
<label asp-for="VillaNumber.VillaId" class="ms-2"></label>
|
||||
<span asp-validation-for="VillaNumber.VillaId" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="VillaNumber.Villa_Number" disabled class="form-control border shadow" />
|
||||
<label asp-for="VillaNumber.Villa_Number" class="ms-2"></label>
|
||||
<span asp-validation-for="VillaNumber.Villa_Number" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-floating py-1 col-12">
|
||||
<input asp-for="VillaNumber.SpecialDetails" class="form-control border shadow" />
|
||||
<label asp-for="VillaNumber.SpecialDetails" class="ms-2"></label>
|
||||
<span asp-validation-for="VillaNumber.SpecialDetails" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="row pt-2">
|
||||
<div class="col-6 col-md-3">
|
||||
<button type="submit" class="btn btn-success w-100">
|
||||
<i class="bi bi-check-circle"></i> Update
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-6 col-md-3">
|
||||
<a asp-controller="VillaNumber" asp-action="Index" class="btn btn-secondary w-100">
|
||||
<i class="bi bi-x-circle"></i> Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts{
|
||||
@{
|
||||
<partial name="_ValidationScriptsPartial" />
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
@using WhiteLagoon.Web
|
||||
@using WhiteLagoon.Web.Models
|
||||
@using WhiteLagoon.Domain.Entities
|
||||
@using WhiteLagoon.Web.ViewModels
|
||||
@using WhiteLagoon.Application.Common.Utility
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@@ -0,0 +1,8 @@
|
||||
@if(User.IsInRole(SD.Role_Admin))
|
||||
{
|
||||
Layout = "_LayoutAdmin";
|
||||
}
|
||||
else
|
||||
{
|
||||
Layout = "_Layout";
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.0-preview.6.23329.4">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0-preview.6.23329.4" />
|
||||
<PackageReference Include="Stripe.net" Version="41.27.0" />
|
||||
<PackageReference Include="Syncfusion.DocIO.Net.Core" Version="22.2.8" />
|
||||
<PackageReference Include="Syncfusion.DocIORenderer.Net.Core" Version="22.2.8" />
|
||||
<PackageReference Include="Syncfusion.Licensing" Version="22.2.8" />
|
||||
<PackageReference Include="Syncfusion.Pdf.Net.Core" Version="22.2.8" />
|
||||
<PackageReference Include="Syncfusion.Presentation.Net.Core" Version="22.2.8" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WhiteLagoon.Infrastructure\WhiteLagoon.Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="wwwroot\images\VillaImage\" />
|
||||
<Folder Include="wwwroot\exports\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=WhiteLagoon;Trusted_Connection=True;TrustServerCertificate=True"
|
||||
},
|
||||
"Stripe": {
|
||||
"SecretKey": "sk_test_51NcXISFiAM4djdaQCMdReHXvyGLRLB73zyRPt8R67JyStbyISjIMxhbVFYFEVrBN4UYjIJrhiwgBRRVteGnTkSpd00N5iMEtPw",
|
||||
"PublishableKey": "pk_test_51NcXISFiAM4djdaQcnZBBwMWOXUD1FW4zUrcOfsMLwJwJR0djCIhKlDo21gauM7JnVAODa0t4rx2VOuaGz9rpVOX00k4NhOH9n"
|
||||
},
|
||||
"Syncfusion": {
|
||||
"Licensekey": "Mgo+DSMBMAY9C3t2V1hhQlJAfV5AQmBIYVp/TGpJfl96cVxMZVVBJAtUQF1hSn5bd0FiWn1Zc3RQTmFd"
|
||||
},
|
||||
"SendGrid": {
|
||||
"Key": "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"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"version": "1.0",
|
||||
"defaultProvider": "jsdelivr",
|
||||
"libraries": [
|
||||
{
|
||||
"library": "jquery-ajax-unobtrusive@3.2.6",
|
||||
"destination": "wwwroot/jquery-ajax-unobtrusive/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,585 @@
|
||||
@keyframes opaque {
|
||||
0% {
|
||||
opacity: 0
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes resizeanim {
|
||||
0%,to {
|
||||
opacity: 0
|
||||
}
|
||||
}
|
||||
|
||||
.apexcharts-canvas {
|
||||
position: relative;
|
||||
user-select: none
|
||||
}
|
||||
|
||||
.apexcharts-canvas ::-webkit-scrollbar {
|
||||
-webkit-appearance: none;
|
||||
width: 6px
|
||||
}
|
||||
|
||||
.apexcharts-canvas ::-webkit-scrollbar-thumb {
|
||||
border-radius: 4px;
|
||||
background-color: rgba(0,0,0,.5);
|
||||
box-shadow: 0 0 1px rgba(255,255,255,.5);
|
||||
-webkit-box-shadow: 0 0 1px rgba(255,255,255,.5)
|
||||
}
|
||||
|
||||
.apexcharts-inner {
|
||||
position: relative
|
||||
}
|
||||
|
||||
.apexcharts-text tspan {
|
||||
font-family: inherit
|
||||
}
|
||||
|
||||
.legend-mouseover-inactive {
|
||||
transition: .15s ease all;
|
||||
opacity: .2
|
||||
}
|
||||
|
||||
.apexcharts-legend-text {
|
||||
padding-left: 15px;
|
||||
margin-left: -15px;
|
||||
}
|
||||
|
||||
.apexcharts-series-collapsed {
|
||||
opacity: 0
|
||||
}
|
||||
|
||||
.apexcharts-tooltip {
|
||||
border-radius: 5px;
|
||||
box-shadow: 2px 2px 6px -4px #999;
|
||||
cursor: default;
|
||||
font-size: 14px;
|
||||
left: 62px;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
z-index: 12;
|
||||
transition: .15s ease all
|
||||
}
|
||||
|
||||
.apexcharts-tooltip.apexcharts-active {
|
||||
opacity: 1;
|
||||
transition: .15s ease all
|
||||
}
|
||||
|
||||
.apexcharts-tooltip.apexcharts-theme-light {
|
||||
border: 1px solid #e3e3e3;
|
||||
background: rgba(255,255,255,.96)
|
||||
}
|
||||
|
||||
.apexcharts-tooltip.apexcharts-theme-dark {
|
||||
color: #fff;
|
||||
background: rgba(30,30,30,.8)
|
||||
}
|
||||
|
||||
.apexcharts-tooltip * {
|
||||
font-family: inherit
|
||||
}
|
||||
|
||||
.apexcharts-tooltip-title {
|
||||
padding: 6px;
|
||||
font-size: 15px;
|
||||
margin-bottom: 4px
|
||||
}
|
||||
|
||||
.apexcharts-tooltip.apexcharts-theme-light .apexcharts-tooltip-title {
|
||||
background: #eceff1;
|
||||
border-bottom: 1px solid #ddd
|
||||
}
|
||||
|
||||
.apexcharts-tooltip.apexcharts-theme-dark .apexcharts-tooltip-title {
|
||||
background: rgba(0,0,0,.7);
|
||||
border-bottom: 1px solid #333
|
||||
}
|
||||
|
||||
.apexcharts-tooltip-text-goals-value,.apexcharts-tooltip-text-y-value,.apexcharts-tooltip-text-z-value {
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
font-weight: 600
|
||||
}
|
||||
|
||||
.apexcharts-tooltip-text-goals-label:empty,.apexcharts-tooltip-text-goals-value:empty,.apexcharts-tooltip-text-y-label:empty,.apexcharts-tooltip-text-y-value:empty,.apexcharts-tooltip-text-z-value:empty,.apexcharts-tooltip-title:empty {
|
||||
display: none
|
||||
}
|
||||
|
||||
.apexcharts-tooltip-text-goals-label,.apexcharts-tooltip-text-goals-value {
|
||||
padding: 6px 0 5px
|
||||
}
|
||||
|
||||
.apexcharts-tooltip-goals-group,.apexcharts-tooltip-text-goals-label,.apexcharts-tooltip-text-goals-value {
|
||||
display: flex
|
||||
}
|
||||
|
||||
.apexcharts-tooltip-text-goals-label:not(:empty),.apexcharts-tooltip-text-goals-value:not(:empty) {
|
||||
margin-top: -6px
|
||||
}
|
||||
|
||||
.apexcharts-tooltip-marker {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
position: relative;
|
||||
top: 0;
|
||||
margin-right: 10px;
|
||||
border-radius: 50%
|
||||
}
|
||||
|
||||
.apexcharts-tooltip-series-group {
|
||||
padding: 0 10px;
|
||||
display: none;
|
||||
text-align: left;
|
||||
justify-content: left;
|
||||
align-items: center
|
||||
}
|
||||
|
||||
.apexcharts-tooltip-series-group.apexcharts-active .apexcharts-tooltip-marker {
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
.apexcharts-tooltip-series-group.apexcharts-active,.apexcharts-tooltip-series-group:last-child {
|
||||
padding-bottom: 4px
|
||||
}
|
||||
|
||||
.apexcharts-tooltip-series-group-hidden {
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
line-height: 0;
|
||||
padding: 0!important
|
||||
}
|
||||
|
||||
.apexcharts-tooltip-y-group {
|
||||
padding: 6px 0 5px
|
||||
}
|
||||
|
||||
.apexcharts-custom-tooltip,.apexcharts-tooltip-box {
|
||||
padding: 4px 8px
|
||||
}
|
||||
|
||||
.apexcharts-tooltip-boxPlot {
|
||||
display: flex;
|
||||
flex-direction: column-reverse
|
||||
}
|
||||
|
||||
.apexcharts-tooltip-box>div {
|
||||
margin: 4px 0
|
||||
}
|
||||
|
||||
.apexcharts-tooltip-box span.value {
|
||||
font-weight: 700
|
||||
}
|
||||
|
||||
.apexcharts-tooltip-rangebar {
|
||||
padding: 5px 8px
|
||||
}
|
||||
|
||||
.apexcharts-tooltip-rangebar .category {
|
||||
font-weight: 600;
|
||||
color: #777
|
||||
}
|
||||
|
||||
.apexcharts-tooltip-rangebar .series-name {
|
||||
font-weight: 700;
|
||||
display: block;
|
||||
margin-bottom: 5px
|
||||
}
|
||||
|
||||
.apexcharts-xaxistooltip,.apexcharts-yaxistooltip {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
color: #373d3f;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
border-radius: 2px;
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
background: #eceff1;
|
||||
border: 1px solid #90a4ae
|
||||
}
|
||||
|
||||
.apexcharts-xaxistooltip {
|
||||
padding: 9px 10px;
|
||||
transition: .15s ease all
|
||||
}
|
||||
|
||||
.apexcharts-xaxistooltip.apexcharts-theme-dark {
|
||||
background: rgba(0,0,0,.7);
|
||||
border: 1px solid rgba(0,0,0,.5);
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.apexcharts-xaxistooltip:after,.apexcharts-xaxistooltip:before {
|
||||
left: 50%;
|
||||
border: solid transparent;
|
||||
content: " ";
|
||||
height: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
pointer-events: none
|
||||
}
|
||||
|
||||
.apexcharts-xaxistooltip:after {
|
||||
border-color: transparent;
|
||||
border-width: 6px;
|
||||
margin-left: -6px
|
||||
}
|
||||
|
||||
.apexcharts-xaxistooltip:before {
|
||||
border-color: transparent;
|
||||
border-width: 7px;
|
||||
margin-left: -7px
|
||||
}
|
||||
|
||||
.apexcharts-xaxistooltip-bottom:after,.apexcharts-xaxistooltip-bottom:before {
|
||||
bottom: 100%
|
||||
}
|
||||
|
||||
.apexcharts-xaxistooltip-top:after,.apexcharts-xaxistooltip-top:before {
|
||||
top: 100%
|
||||
}
|
||||
|
||||
.apexcharts-xaxistooltip-bottom:after {
|
||||
border-bottom-color: #eceff1
|
||||
}
|
||||
|
||||
.apexcharts-xaxistooltip-bottom:before {
|
||||
border-bottom-color: #90a4ae
|
||||
}
|
||||
|
||||
.apexcharts-xaxistooltip-bottom.apexcharts-theme-dark:after,.apexcharts-xaxistooltip-bottom.apexcharts-theme-dark:before {
|
||||
border-bottom-color: rgba(0,0,0,.5)
|
||||
}
|
||||
|
||||
.apexcharts-xaxistooltip-top:after {
|
||||
border-top-color: #eceff1
|
||||
}
|
||||
|
||||
.apexcharts-xaxistooltip-top:before {
|
||||
border-top-color: #90a4ae
|
||||
}
|
||||
|
||||
.apexcharts-xaxistooltip-top.apexcharts-theme-dark:after,.apexcharts-xaxistooltip-top.apexcharts-theme-dark:before {
|
||||
border-top-color: rgba(0,0,0,.5)
|
||||
}
|
||||
|
||||
.apexcharts-xaxistooltip.apexcharts-active {
|
||||
opacity: 1;
|
||||
transition: .15s ease all
|
||||
}
|
||||
|
||||
.apexcharts-yaxistooltip {
|
||||
padding: 4px 10px
|
||||
}
|
||||
|
||||
.apexcharts-yaxistooltip.apexcharts-theme-dark {
|
||||
background: rgba(0,0,0,.7);
|
||||
border: 1px solid rgba(0,0,0,.5);
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.apexcharts-yaxistooltip:after,.apexcharts-yaxistooltip:before {
|
||||
top: 50%;
|
||||
border: solid transparent;
|
||||
content: " ";
|
||||
height: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
pointer-events: none
|
||||
}
|
||||
|
||||
.apexcharts-yaxistooltip:after {
|
||||
border-color: transparent;
|
||||
border-width: 6px;
|
||||
margin-top: -6px
|
||||
}
|
||||
|
||||
.apexcharts-yaxistooltip:before {
|
||||
border-color: transparent;
|
||||
border-width: 7px;
|
||||
margin-top: -7px
|
||||
}
|
||||
|
||||
.apexcharts-yaxistooltip-left:after,.apexcharts-yaxistooltip-left:before {
|
||||
left: 100%
|
||||
}
|
||||
|
||||
.apexcharts-yaxistooltip-right:after,.apexcharts-yaxistooltip-right:before {
|
||||
right: 100%
|
||||
}
|
||||
|
||||
.apexcharts-yaxistooltip-left:after {
|
||||
border-left-color: #eceff1
|
||||
}
|
||||
|
||||
.apexcharts-yaxistooltip-left:before {
|
||||
border-left-color: #90a4ae
|
||||
}
|
||||
|
||||
.apexcharts-yaxistooltip-left.apexcharts-theme-dark:after,.apexcharts-yaxistooltip-left.apexcharts-theme-dark:before {
|
||||
border-left-color: rgba(0,0,0,.5)
|
||||
}
|
||||
|
||||
.apexcharts-yaxistooltip-right:after {
|
||||
border-right-color: #eceff1
|
||||
}
|
||||
|
||||
.apexcharts-yaxistooltip-right:before {
|
||||
border-right-color: #90a4ae
|
||||
}
|
||||
|
||||
.apexcharts-yaxistooltip-right.apexcharts-theme-dark:after,.apexcharts-yaxistooltip-right.apexcharts-theme-dark:before {
|
||||
border-right-color: rgba(0,0,0,.5)
|
||||
}
|
||||
|
||||
.apexcharts-yaxistooltip.apexcharts-active {
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
.apexcharts-yaxistooltip-hidden {
|
||||
display: none
|
||||
}
|
||||
|
||||
.apexcharts-xcrosshairs,.apexcharts-ycrosshairs {
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
transition: .15s ease all
|
||||
}
|
||||
|
||||
.apexcharts-xcrosshairs.apexcharts-active,.apexcharts-ycrosshairs.apexcharts-active {
|
||||
opacity: 1;
|
||||
transition: .15s ease all
|
||||
}
|
||||
|
||||
.apexcharts-ycrosshairs-hidden {
|
||||
opacity: 0
|
||||
}
|
||||
|
||||
.apexcharts-selection-rect {
|
||||
cursor: move
|
||||
}
|
||||
|
||||
.svg_select_boundingRect,.svg_select_points_rot {
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
visibility: hidden
|
||||
}
|
||||
|
||||
.apexcharts-selection-rect+g .svg_select_boundingRect,.apexcharts-selection-rect+g .svg_select_points_rot {
|
||||
opacity: 0;
|
||||
visibility: hidden
|
||||
}
|
||||
|
||||
.apexcharts-selection-rect+g .svg_select_points_l,.apexcharts-selection-rect+g .svg_select_points_r {
|
||||
cursor: ew-resize;
|
||||
opacity: 1;
|
||||
visibility: visible
|
||||
}
|
||||
|
||||
.svg_select_points {
|
||||
fill: #efefef;
|
||||
stroke: #333;
|
||||
rx: 2
|
||||
}
|
||||
|
||||
.apexcharts-svg.apexcharts-zoomable.hovering-zoom {
|
||||
cursor: crosshair
|
||||
}
|
||||
|
||||
.apexcharts-svg.apexcharts-zoomable.hovering-pan {
|
||||
cursor: move
|
||||
}
|
||||
|
||||
.apexcharts-menu-icon,.apexcharts-pan-icon,.apexcharts-reset-icon,.apexcharts-selection-icon,.apexcharts-toolbar-custom-icon,.apexcharts-zoom-icon,.apexcharts-zoomin-icon,.apexcharts-zoomout-icon {
|
||||
cursor: pointer;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
line-height: 24px;
|
||||
color: #6e8192;
|
||||
text-align: center
|
||||
}
|
||||
|
||||
.apexcharts-menu-icon svg,.apexcharts-reset-icon svg,.apexcharts-zoom-icon svg,.apexcharts-zoomin-icon svg,.apexcharts-zoomout-icon svg {
|
||||
fill: #6e8192
|
||||
}
|
||||
|
||||
.apexcharts-selection-icon svg {
|
||||
fill: #444;
|
||||
transform: scale(.76)
|
||||
}
|
||||
|
||||
.apexcharts-theme-dark .apexcharts-menu-icon svg,.apexcharts-theme-dark .apexcharts-pan-icon svg,.apexcharts-theme-dark .apexcharts-reset-icon svg,.apexcharts-theme-dark .apexcharts-selection-icon svg,.apexcharts-theme-dark .apexcharts-toolbar-custom-icon svg,.apexcharts-theme-dark .apexcharts-zoom-icon svg,.apexcharts-theme-dark .apexcharts-zoomin-icon svg,.apexcharts-theme-dark .apexcharts-zoomout-icon svg {
|
||||
fill: #f3f4f5
|
||||
}
|
||||
|
||||
.apexcharts-canvas .apexcharts-reset-zoom-icon.apexcharts-selected svg,.apexcharts-canvas .apexcharts-selection-icon.apexcharts-selected svg,.apexcharts-canvas .apexcharts-zoom-icon.apexcharts-selected svg {
|
||||
fill: #008ffb
|
||||
}
|
||||
|
||||
.apexcharts-theme-light .apexcharts-menu-icon:hover svg,.apexcharts-theme-light .apexcharts-reset-icon:hover svg,.apexcharts-theme-light .apexcharts-selection-icon:not(.apexcharts-selected):hover svg,.apexcharts-theme-light .apexcharts-zoom-icon:not(.apexcharts-selected):hover svg,.apexcharts-theme-light .apexcharts-zoomin-icon:hover svg,.apexcharts-theme-light .apexcharts-zoomout-icon:hover svg {
|
||||
fill: #333
|
||||
}
|
||||
|
||||
.apexcharts-menu-icon,.apexcharts-selection-icon {
|
||||
position: relative
|
||||
}
|
||||
|
||||
.apexcharts-reset-icon {
|
||||
margin-left: 5px
|
||||
}
|
||||
|
||||
.apexcharts-menu-icon,.apexcharts-reset-icon,.apexcharts-zoom-icon {
|
||||
transform: scale(.85)
|
||||
}
|
||||
|
||||
.apexcharts-zoomin-icon,.apexcharts-zoomout-icon {
|
||||
transform: scale(.7)
|
||||
}
|
||||
|
||||
.apexcharts-zoomout-icon {
|
||||
margin-right: 3px
|
||||
}
|
||||
|
||||
.apexcharts-pan-icon {
|
||||
transform: scale(.62);
|
||||
position: relative;
|
||||
left: 1px;
|
||||
top: 0
|
||||
}
|
||||
|
||||
.apexcharts-pan-icon svg {
|
||||
fill: #fff;
|
||||
stroke: #6e8192;
|
||||
stroke-width: 2
|
||||
}
|
||||
|
||||
.apexcharts-pan-icon.apexcharts-selected svg {
|
||||
stroke: #008ffb
|
||||
}
|
||||
|
||||
.apexcharts-pan-icon:not(.apexcharts-selected):hover svg {
|
||||
stroke: #333
|
||||
}
|
||||
|
||||
.apexcharts-toolbar {
|
||||
position: absolute;
|
||||
z-index: 11;
|
||||
max-width: 176px;
|
||||
text-align: right;
|
||||
border-radius: 3px;
|
||||
padding: 0 6px 2px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center
|
||||
}
|
||||
|
||||
.apexcharts-menu {
|
||||
background: #fff;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
padding: 3px;
|
||||
right: 10px;
|
||||
opacity: 0;
|
||||
min-width: 110px;
|
||||
transition: .15s ease all;
|
||||
pointer-events: none
|
||||
}
|
||||
|
||||
.apexcharts-menu.apexcharts-menu-open {
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
transition: .15s ease all
|
||||
}
|
||||
|
||||
.apexcharts-menu-item {
|
||||
padding: 6px 7px;
|
||||
font-size: 12px;
|
||||
cursor: pointer
|
||||
}
|
||||
|
||||
.apexcharts-theme-light .apexcharts-menu-item:hover {
|
||||
background: #eee
|
||||
}
|
||||
|
||||
.apexcharts-theme-dark .apexcharts-menu {
|
||||
background: rgba(0,0,0,.7);
|
||||
color: #fff
|
||||
}
|
||||
|
||||
@media screen and (min-width:768px) {
|
||||
.apexcharts-canvas:hover .apexcharts-toolbar {
|
||||
opacity: 1
|
||||
}
|
||||
}
|
||||
|
||||
.apexcharts-canvas .apexcharts-element-hidden,.apexcharts-datalabel.apexcharts-element-hidden,.apexcharts-hide .apexcharts-series-points {
|
||||
opacity: 0
|
||||
}
|
||||
|
||||
.apexcharts-hidden-element-shown {
|
||||
opacity: 1;
|
||||
transition: 0.25s ease all;
|
||||
}
|
||||
.apexcharts-datalabel,.apexcharts-datalabel-label,.apexcharts-datalabel-value,.apexcharts-datalabels,.apexcharts-pie-label {
|
||||
cursor: default;
|
||||
pointer-events: none
|
||||
}
|
||||
|
||||
.apexcharts-pie-label-delay {
|
||||
opacity: 0;
|
||||
animation-name: opaque;
|
||||
animation-duration: .3s;
|
||||
animation-fill-mode: forwards;
|
||||
animation-timing-function: ease
|
||||
}
|
||||
|
||||
.apexcharts-annotation-rect,.apexcharts-area-series .apexcharts-area,.apexcharts-area-series .apexcharts-series-markers .apexcharts-marker.no-pointer-events,.apexcharts-gridline,.apexcharts-line,.apexcharts-line-series .apexcharts-series-markers .apexcharts-marker.no-pointer-events,.apexcharts-point-annotation-label,.apexcharts-radar-series path,.apexcharts-radar-series polygon,.apexcharts-toolbar svg,.apexcharts-tooltip .apexcharts-marker,.apexcharts-xaxis-annotation-label,.apexcharts-yaxis-annotation-label,.apexcharts-zoom-rect {
|
||||
pointer-events: none
|
||||
}
|
||||
|
||||
.apexcharts-marker {
|
||||
transition: .15s ease all
|
||||
}
|
||||
|
||||
.resize-triggers {
|
||||
animation: 1ms resizeanim;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
.contract-trigger:before,.resize-triggers,.resize-triggers>div {
|
||||
content: " ";
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0
|
||||
}
|
||||
|
||||
.resize-triggers>div {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: #eee;
|
||||
overflow: auto
|
||||
}
|
||||
|
||||
.contract-trigger:before {
|
||||
overflow: hidden;
|
||||
width: 200%;
|
||||
height: 200%
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
html {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
html {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
|
||||
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
|
||||
}
|
||||
|
||||
html {
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
.dataTables_filter{
|
||||
margin-bottom:20px;
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/* Absolute Center Spinner */
|
||||
.loading {
|
||||
position: fixed;
|
||||
z-index: 999;
|
||||
overflow: show;
|
||||
margin: auto;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
/* Transparent Overlay */
|
||||
.loading:before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
/* :not(:required) hides these rules from IE9 and below */
|
||||
.loading:not(:required) {
|
||||
/* hide "loading..." text */
|
||||
font: 0/0 a;
|
||||
color: transparent;
|
||||
text-shadow: none;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.loading:not(:required):after {
|
||||
content: '';
|
||||
display: block;
|
||||
font-size: 10px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin-top: -0.5em;
|
||||
border: 5px solid rgba(33, 150, 243, 1.0);
|
||||
border-radius: 100%;
|
||||
border-bottom-color: transparent;
|
||||
-webkit-animation: spinner 1s linear 0s infinite;
|
||||
animation: spinner 1s linear 0s infinite;
|
||||
}
|
||||
|
||||
/* Animation */
|
||||
|
||||
@-webkit-keyframes spinner {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-ms-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
-moz-transform: rotate(360deg);
|
||||
-ms-transform: rotate(360deg);
|
||||
-o-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@-moz-keyframes spinner {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-ms-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
-moz-transform: rotate(360deg);
|
||||
-ms-transform: rotate(360deg);
|
||||
-o-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@-o-keyframes spinner {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-ms-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
-moz-transform: rotate(360deg);
|
||||
-ms-transform: rotate(360deg);
|
||||
-o-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spinner {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-ms-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
-moz-transform: rotate(360deg);
|
||||
-ms-transform: rotate(360deg);
|
||||
-o-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 318 KiB |
|
After Width: | Height: | Size: 364 KiB |
|
After Width: | Height: | Size: 332 KiB |
|
After Width: | Height: | Size: 371 KiB |
|
After Width: | Height: | Size: 321 KiB |
|
After Width: | Height: | Size: 171 KiB |
|
After Width: | Height: | Size: 369 KiB |
|
After Width: | Height: | Size: 371 KiB |
|
After Width: | Height: | Size: 364 KiB |
|
After Width: | Height: | Size: 321 KiB |
|
After Width: | Height: | Size: 439 KiB |
|
After Width: | Height: | Size: 375 KiB |
|
After Width: | Height: | Size: 13 MiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 2.5 MiB |
|
After Width: | Height: | Size: 2.3 MiB |
@@ -0,0 +1,12 @@
|
||||
Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
these files except in compliance with the License. You may obtain a copy of the
|
||||
License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software distributed
|
||||
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations under the License.
|
||||
@@ -0,0 +1,10 @@
|
||||
jQuery Unobtrusive Ajax
|
||||
=============================
|
||||
|
||||
The jQuery Unobtrusive Ajax library complements jQuery Ajax methods by adding support for specifying options for HTML replacement via Ajax calls as HTML5 `data-*` elements.
|
||||
|
||||
This project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [Home](https://github.com/aspnet/home) repo.
|
||||
|
||||
Remember to make your changes to only the src file. Use ".\build.cmd" to automatically generate the js file in dist directory, minify the js file, create a .nupkg and change the version in the package.json if needed.
|
||||
|
||||
To stage for a release, update the "version.props" file and run ".\build.cmd" (see Release Checklist [here](https://github.com/aspnet/jquery-ajax-unobtrusive/wiki/Release-checklist)).
|
||||
@@ -0,0 +1,205 @@
|
||||
// Unobtrusive Ajax support library for jQuery
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// @version v3.2.6
|
||||
//
|
||||
// Microsoft grants you the right to use these script files for the sole
|
||||
// purpose of either: (i) interacting through your browser with the Microsoft
|
||||
// website or online service, subject to the applicable licensing or use
|
||||
// terms; or (ii) using the files as included with a Microsoft product subject
|
||||
// to that product's license terms. Microsoft reserves all other rights to the
|
||||
// files not expressly granted by Microsoft, whether by implication, estoppel
|
||||
// or otherwise. Insofar as a script file is dual licensed under GPL,
|
||||
// Microsoft neither took the code under GPL nor distributes it thereunder but
|
||||
// under the terms set out in this paragraph. All notices and licenses
|
||||
// below are for informational purposes only.
|
||||
|
||||
/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */
|
||||
/*global window: false, jQuery: false */
|
||||
|
||||
(function ($) {
|
||||
var data_click = "unobtrusiveAjaxClick",
|
||||
data_target = "unobtrusiveAjaxClickTarget",
|
||||
data_validation = "unobtrusiveValidation";
|
||||
|
||||
function getFunction(code, argNames) {
|
||||
var fn = window, parts = (code || "").split(".");
|
||||
while (fn && parts.length) {
|
||||
fn = fn[parts.shift()];
|
||||
}
|
||||
if (typeof (fn) === "function") {
|
||||
return fn;
|
||||
}
|
||||
argNames.push(code);
|
||||
return Function.constructor.apply(null, argNames);
|
||||
}
|
||||
|
||||
function isMethodProxySafe(method) {
|
||||
return method === "GET" || method === "POST";
|
||||
}
|
||||
|
||||
function asyncOnBeforeSend(xhr, method) {
|
||||
if (!isMethodProxySafe(method)) {
|
||||
xhr.setRequestHeader("X-HTTP-Method-Override", method);
|
||||
}
|
||||
}
|
||||
|
||||
function asyncOnSuccess(element, data, contentType) {
|
||||
var mode;
|
||||
|
||||
if (contentType.indexOf("application/x-javascript") !== -1) { // jQuery already executes JavaScript for us
|
||||
return;
|
||||
}
|
||||
|
||||
mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase();
|
||||
$(element.getAttribute("data-ajax-update")).each(function (i, update) {
|
||||
var top;
|
||||
|
||||
switch (mode) {
|
||||
case "BEFORE":
|
||||
$(update).prepend(data);
|
||||
break;
|
||||
case "AFTER":
|
||||
$(update).append(data);
|
||||
break;
|
||||
case "REPLACE-WITH":
|
||||
$(update).replaceWith(data);
|
||||
break;
|
||||
default:
|
||||
$(update).html(data);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function asyncRequest(element, options) {
|
||||
var confirm, loading, method, duration;
|
||||
|
||||
confirm = element.getAttribute("data-ajax-confirm");
|
||||
if (confirm && !window.confirm(confirm)) {
|
||||
return;
|
||||
}
|
||||
|
||||
loading = $(element.getAttribute("data-ajax-loading"));
|
||||
duration = parseInt(element.getAttribute("data-ajax-loading-duration"), 10) || 0;
|
||||
|
||||
$.extend(options, {
|
||||
type: element.getAttribute("data-ajax-method") || undefined,
|
||||
url: element.getAttribute("data-ajax-url") || undefined,
|
||||
cache: (element.getAttribute("data-ajax-cache") || "").toLowerCase() === "true",
|
||||
beforeSend: function (xhr) {
|
||||
var result;
|
||||
asyncOnBeforeSend(xhr, method);
|
||||
result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(element, arguments);
|
||||
if (result !== false) {
|
||||
loading.show(duration);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
complete: function () {
|
||||
loading.hide(duration);
|
||||
getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(element, arguments);
|
||||
},
|
||||
success: function (data, status, xhr) {
|
||||
asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html");
|
||||
getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(element, arguments);
|
||||
},
|
||||
error: function () {
|
||||
getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]).apply(element, arguments);
|
||||
}
|
||||
});
|
||||
|
||||
options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" });
|
||||
|
||||
method = options.type.toUpperCase();
|
||||
if (!isMethodProxySafe(method)) {
|
||||
options.type = "POST";
|
||||
options.data.push({ name: "X-HTTP-Method-Override", value: method });
|
||||
}
|
||||
|
||||
// change here:
|
||||
// Check for a Form POST with enctype=multipart/form-data
|
||||
// add the input file that were not previously included in the serializeArray()
|
||||
// set processData and contentType to false
|
||||
var $element = $(element);
|
||||
if ($element.is("form") && $element.attr("enctype") == "multipart/form-data") {
|
||||
var formdata = new FormData();
|
||||
$.each(options.data, function (i, v) {
|
||||
formdata.append(v.name, v.value);
|
||||
});
|
||||
$("input[type=file]", $element).each(function () {
|
||||
var file = this;
|
||||
$.each(file.files, function (n, v) {
|
||||
formdata.append(file.name, v);
|
||||
});
|
||||
});
|
||||
$.extend(options, {
|
||||
processData: false,
|
||||
contentType: false,
|
||||
data: formdata
|
||||
});
|
||||
}
|
||||
// end change
|
||||
|
||||
$.ajax(options);
|
||||
}
|
||||
|
||||
function validate(form) {
|
||||
var validationInfo = $(form).data(data_validation);
|
||||
return !validationInfo || !validationInfo.validate || validationInfo.validate();
|
||||
}
|
||||
|
||||
$(document).on("click", "a[data-ajax=true]", function (evt) {
|
||||
evt.preventDefault();
|
||||
asyncRequest(this, {
|
||||
url: this.href,
|
||||
type: "GET",
|
||||
data: []
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on("click", "form[data-ajax=true] input[type=image]", function (evt) {
|
||||
var name = evt.target.name,
|
||||
target = $(evt.target),
|
||||
form = $(target.parents("form")[0]),
|
||||
offset = target.offset();
|
||||
|
||||
form.data(data_click, [
|
||||
{ name: name + ".x", value: Math.round(evt.pageX - offset.left) },
|
||||
{ name: name + ".y", value: Math.round(evt.pageY - offset.top) }
|
||||
]);
|
||||
|
||||
setTimeout(function () {
|
||||
form.removeData(data_click);
|
||||
}, 0);
|
||||
});
|
||||
|
||||
$(document).on("click", "form[data-ajax=true] :submit", function (evt) {
|
||||
var name = evt.currentTarget.name,
|
||||
target = $(evt.target),
|
||||
form = $(target.parents("form")[0]);
|
||||
|
||||
form.data(data_click, name ? [{ name: name, value: evt.currentTarget.value }] : []);
|
||||
form.data(data_target, target);
|
||||
|
||||
setTimeout(function () {
|
||||
form.removeData(data_click);
|
||||
form.removeData(data_target);
|
||||
}, 0);
|
||||
});
|
||||
|
||||
$(document).on("submit", "form[data-ajax=true]", function (evt) {
|
||||
var clickInfo = $(this).data(data_click) || [],
|
||||
clickTarget = $(this).data(data_target),
|
||||
isCancel = clickTarget && (clickTarget.hasClass("cancel") || clickTarget.attr('formnovalidate') !== undefined);
|
||||
evt.preventDefault();
|
||||
if (!isCancel && !validate(this)) {
|
||||
return;
|
||||
}
|
||||
asyncRequest(this, {
|
||||
url: this.action,
|
||||
type: this.method || "GET",
|
||||
data: clickInfo.concat($(this).serializeArray())
|
||||
});
|
||||
});
|
||||
}(jQuery));
|
||||
@@ -0,0 +1,16 @@
|
||||
// Unobtrusive Ajax support library for jQuery
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// @version v3.2.6
|
||||
//
|
||||
// Microsoft grants you the right to use these script files for the sole
|
||||
// purpose of either: (i) interacting through your browser with the Microsoft
|
||||
// website or online service, subject to the applicable licensing or use
|
||||
// terms; or (ii) using the files as included with a Microsoft product subject
|
||||
// to that product's license terms. Microsoft reserves all other rights to the
|
||||
// files not expressly granted by Microsoft, whether by implication, estoppel
|
||||
// or otherwise. Insofar as a script file is dual licensed under GPL,
|
||||
// Microsoft neither took the code under GPL nor distributes it thereunder but
|
||||
// under the terms set out in this paragraph. All notices and licenses
|
||||
// below are for informational purposes only.
|
||||
!function(t){function a(t,a){for(var e=window,r=(t||"").split(".");e&&r.length;)e=e[r.shift()];return"function"==typeof e?e:(a.push(t),Function.constructor.apply(null,a))}function e(t){return"GET"===t||"POST"===t}function r(t,a){e(a)||t.setRequestHeader("X-HTTP-Method-Override",a)}function n(a,e,r){var n;r.indexOf("application/x-javascript")===-1&&(n=(a.getAttribute("data-ajax-mode")||"").toUpperCase(),t(a.getAttribute("data-ajax-update")).each(function(a,r){switch(n){case"BEFORE":t(r).prepend(e);break;case"AFTER":t(r).append(e);break;case"REPLACE-WITH":t(r).replaceWith(e);break;default:t(r).html(e)}}))}function i(i,u){var o,c,d,s;if(o=i.getAttribute("data-ajax-confirm"),!o||window.confirm(o)){c=t(i.getAttribute("data-ajax-loading")),s=parseInt(i.getAttribute("data-ajax-loading-duration"),10)||0,t.extend(u,{type:i.getAttribute("data-ajax-method")||void 0,url:i.getAttribute("data-ajax-url")||void 0,cache:"true"===(i.getAttribute("data-ajax-cache")||"").toLowerCase(),beforeSend:function(t){var e;return r(t,d),e=a(i.getAttribute("data-ajax-begin"),["xhr"]).apply(i,arguments),e!==!1&&c.show(s),e},complete:function(){c.hide(s),a(i.getAttribute("data-ajax-complete"),["xhr","status"]).apply(i,arguments)},success:function(t,e,r){n(i,t,r.getResponseHeader("Content-Type")||"text/html"),a(i.getAttribute("data-ajax-success"),["data","status","xhr"]).apply(i,arguments)},error:function(){a(i.getAttribute("data-ajax-failure"),["xhr","status","error"]).apply(i,arguments)}}),u.data.push({name:"X-Requested-With",value:"XMLHttpRequest"}),d=u.type.toUpperCase(),e(d)||(u.type="POST",u.data.push({name:"X-HTTP-Method-Override",value:d}));var p=t(i);if(p.is("form")&&"multipart/form-data"==p.attr("enctype")){var f=new FormData;t.each(u.data,function(t,a){f.append(a.name,a.value)}),t("input[type=file]",p).each(function(){var a=this;t.each(a.files,function(t,e){f.append(a.name,e)})}),t.extend(u,{processData:!1,contentType:!1,data:f})}t.ajax(u)}}function u(a){var e=t(a).data(d);return!e||!e.validate||e.validate()}var o="unobtrusiveAjaxClick",c="unobtrusiveAjaxClickTarget",d="unobtrusiveValidation";t(document).on("click","a[data-ajax=true]",function(t){t.preventDefault(),i(this,{url:this.href,type:"GET",data:[]})}),t(document).on("click","form[data-ajax=true] input[type=image]",function(a){var e=a.target.name,r=t(a.target),n=t(r.parents("form")[0]),i=r.offset();n.data(o,[{name:e+".x",value:Math.round(a.pageX-i.left)},{name:e+".y",value:Math.round(a.pageY-i.top)}]),setTimeout(function(){n.removeData(o)},0)}),t(document).on("click","form[data-ajax=true] :submit",function(a){var e=a.currentTarget.name,r=t(a.target),n=t(r.parents("form")[0]);n.data(o,e?[{name:e,value:a.currentTarget.value}]:[]),n.data(c,r),setTimeout(function(){n.removeData(o),n.removeData(c)},0)}),t(document).on("submit","form[data-ajax=true]",function(a){var e=t(this).data(o)||[],r=t(this).data(c),n=r&&(r.hasClass("cancel")||void 0!==r.attr("formnovalidate"));a.preventDefault(),(n||u(this))&&i(this,{url:this.action,type:this.method||"GET",data:e.concat(t(this).serializeArray())})})}(jQuery);
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "jquery-ajax-unobtrusive",
|
||||
"version": "3.2.6",
|
||||
"description": "Add-on to jQuery Ajax to enable unobtrusive options in data-* attributes",
|
||||
"main": "dist/jquery.unobtrusive-ajax.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aspnet/jquery-ajax-unobtrusive"
|
||||
},
|
||||
"keywords": [
|
||||
"unobtrusive",
|
||||
"ajax",
|
||||
"mvc",
|
||||
"asp.net",
|
||||
"jquery"
|
||||
],
|
||||
"author": "Microsoft",
|
||||
"license": "https://aka.ms/jquery-ajax-license",
|
||||
"bugs": {
|
||||
"url": "https://github.com/aspnet/jquery-ajax-unobtrusive/issues"
|
||||
},
|
||||
"homepage": "https://github.com/aspnet/jquery-ajax-unobtrusive",
|
||||
"files": [
|
||||
"dist/jquery.unobtrusive-ajax.js",
|
||||
"dist/jquery.unobtrusive-ajax.min.js"
|
||||
],
|
||||
"dependencies": {
|
||||
"jquery": ">=1.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"gulp": "^4.0.0",
|
||||
"gulp-cli": "1.2.2",
|
||||
"gulp-line-ending-corrector": "1.0.1",
|
||||
"gulp-rename": "1.2.2",
|
||||
"gulp-replace": "0.5.4",
|
||||
"gulp-uglify": "2.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm install && gulp"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
var dataTable;
|
||||
|
||||
|
||||
$(document).ready(function () {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const status = urlParams.get('status');
|
||||
loadDataTable(status);
|
||||
|
||||
});
|
||||
|
||||
|
||||
function loadDataTable(status) {
|
||||
dataTable = $('#tblBookings').DataTable({
|
||||
"ajax": {
|
||||
url: '/booking/getall?status='+status
|
||||
},
|
||||
"columns": [
|
||||
{ data: 'id', "width": "5%" },
|
||||
{ data: 'name', "width": "15%" },
|
||||
{ data: 'phone', "width": "10%" },
|
||||
{ data: 'email', "width": "15%" },
|
||||
{ data: 'status', "width": "10%" },
|
||||
{ data: 'checkInDate', "width": "10%" },
|
||||
{ data: 'nights', "width": "10%" },
|
||||
{ data: 'totalCost', render: $.fn.dataTable.render.number(',', '.', 2) , "width": "10%" },
|
||||
{
|
||||
data: 'id',
|
||||
"render": function (data) {
|
||||
return `<div class="w-75 btn-group">
|
||||
<a href="/booking/bookingDetails?bookingId=${data}" class="btn btn-outline-warning mx-2">
|
||||
<i class="bi bi-pencil-square"></i> Details
|
||||
</a>
|
||||
</div>`
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
|
||||
$(document).ready(function () {
|
||||
loadCustomerAndBookingLineChart();
|
||||
});
|
||||
|
||||
function loadCustomerAndBookingLineChart() {
|
||||
$(".chart-spinner").show();
|
||||
|
||||
$.ajax({
|
||||
url: "/Dashboard/GetMemberAndBookingLineChartData",
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
|
||||
loadLineChart("newMembersAndBookingsLineChart", data);
|
||||
|
||||
$(".chart-spinner").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadLineChart(id, data) {
|
||||
var chartColors = getChartColorsArray(id);
|
||||
var options = {
|
||||
colors: chartColors,
|
||||
chart: {
|
||||
height: 350,
|
||||
//show area later
|
||||
type: 'line',
|
||||
zoom: {
|
||||
type: 'x',
|
||||
enabled: true,
|
||||
autoScaleYaxis: true
|
||||
},
|
||||
},
|
||||
stroke: {
|
||||
curve: 'smooth',
|
||||
width: 2
|
||||
},
|
||||
series: data.series,
|
||||
dataLabels: {
|
||||
enabled: false,
|
||||
},
|
||||
markers: {
|
||||
size: 6,
|
||||
strokeWidth: 0,
|
||||
hover: {
|
||||
size: 9
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
categories: data.categories,
|
||||
labels: {
|
||||
style: {
|
||||
colors: "#fff",
|
||||
},
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
labels: {
|
||||
//formatter: function (val) {
|
||||
// return val.toFixed(0);
|
||||
//},
|
||||
style: {
|
||||
colors: "#fff",
|
||||
},
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
labels: {
|
||||
colors: "#fff",
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
theme: 'dark'
|
||||
}
|
||||
};
|
||||
var chart = new ApexCharts(document.querySelector("#" + id), options);
|
||||
chart.render();
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
|
||||
$(document).ready(function () {
|
||||
loadCustomerBookingPieChart();
|
||||
});
|
||||
|
||||
function loadCustomerBookingPieChart() {
|
||||
$(".chart-spinner").show();
|
||||
|
||||
$.ajax({
|
||||
url: "/Dashboard/GetBookingPieChartData",
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
|
||||
loadPieChart("customerBookingsPieChart", data);
|
||||
|
||||
$(".chart-spinner").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadPieChart(id, data) {
|
||||
var chartColors = getChartColorsArray(id);
|
||||
var options = {
|
||||
colors: chartColors,
|
||||
series: data.series,
|
||||
labels: data.labels,
|
||||
chart: {
|
||||
width: 380,
|
||||
type: 'pie',
|
||||
},
|
||||
stroke: {
|
||||
show: false
|
||||
},
|
||||
legend: {
|
||||
position: 'bottom',
|
||||
horizontalAlign: 'center',
|
||||
labels: {
|
||||
colors: "#fff",
|
||||
useSeriesColors: true
|
||||
},
|
||||
},
|
||||
};
|
||||
var chart = new ApexCharts(document.querySelector("#" + id), options);
|
||||
chart.render();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
$(document).ready(function () {
|
||||
loadTotalBookingRadialChart();
|
||||
});
|
||||
|
||||
function loadTotalBookingRadialChart() {
|
||||
$(".chart-spinner").show();
|
||||
|
||||
$.ajax({
|
||||
url: "/Dashboard/GetTotalBookingRadialChartData",
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
document.querySelector("#spanTotalBookingCount").innerHTML = data.totalCount;
|
||||
|
||||
var sectionCurrentCount = document.createElement("span");
|
||||
if (data.hasRatioIncreased) {
|
||||
sectionCurrentCount.className = "text-success me-1";
|
||||
sectionCurrentCount.innerHTML = '<i class="bi bi-arrow-up-right-circle me-1"></i> <span> ' + data.countInCurrentMonth + '</span>';
|
||||
}
|
||||
else {
|
||||
sectionCurrentCount.className = "text-danger me-1";
|
||||
sectionCurrentCount.innerHTML = '<i class="bi bi-arrow-down-right-circle me-1"></i> <span> ' + data.countInCurrentMonth + '</span>';
|
||||
}
|
||||
|
||||
document.querySelector("#sectionBookingCount").append(sectionCurrentCount);
|
||||
document.querySelector("#sectionBookingCount").append("since last month");
|
||||
|
||||
loadRadialBarChart("totalBookingsRadialChart", data);
|
||||
|
||||
$(".chart-spinner").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
$(document).ready(function () {
|
||||
loadRevenueRadialChart();
|
||||
});
|
||||
|
||||
function loadRevenueRadialChart() {
|
||||
$(".chart-spinner").show();
|
||||
|
||||
$.ajax({
|
||||
url: "/Dashboard/GetRevenueChartData",
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
document.querySelector("#spanTotalRevenueCount").innerHTML = data.totalCount;
|
||||
|
||||
var sectionCurrentCount = document.createElement("span");
|
||||
if (data.hasRatioIncreased) {
|
||||
sectionCurrentCount.className = "text-success me-1";
|
||||
sectionCurrentCount.innerHTML = '<i class="bi bi-arrow-up-right-circle me-1"></i> <span> ' + data.countInCurrentMonth + '</span>';
|
||||
}
|
||||
else {
|
||||
sectionCurrentCount.className = "text-danger me-1";
|
||||
sectionCurrentCount.innerHTML = '<i class="bi bi-arrow-down-right-circle me-1"></i> <span> ' + data.countInCurrentMonth + '</span>';
|
||||
}
|
||||
|
||||
document.querySelector("#sectionRevenueCount").append(sectionCurrentCount);
|
||||
document.querySelector("#sectionRevenueCount").append("since last month");
|
||||
|
||||
loadRadialBarChart("totalRevenueRadialChart", data);
|
||||
|
||||
$(".chart-spinner").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
$(document).ready(function () {
|
||||
loadUserRadialChart();
|
||||
});
|
||||
|
||||
function loadUserRadialChart() {
|
||||
$(".chart-spinner").show();
|
||||
|
||||
$.ajax({
|
||||
url: "/Dashboard/GetRegisteredUserChartData",
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
document.querySelector("#spanTotalUserCount").innerHTML = data.totalCount;
|
||||
|
||||
var sectionCurrentCount = document.createElement("span");
|
||||
if (data.hasRatioIncreased) {
|
||||
sectionCurrentCount.className = "text-success me-1";
|
||||
sectionCurrentCount.innerHTML = '<i class="bi bi-arrow-up-right-circle me-1"></i> <span> ' + data.countInCurrentMonth + '</span>';
|
||||
}
|
||||
else {
|
||||
sectionCurrentCount.className = "text-danger me-1";
|
||||
sectionCurrentCount.innerHTML = '<i class="bi bi-arrow-down-right-circle me-1"></i> <span> ' + data.countInCurrentMonth + '</span>';
|
||||
}
|
||||
|
||||
document.querySelector("#sectionUserCount").append(sectionCurrentCount);
|
||||
document.querySelector("#sectionUserCount").append("since last month");
|
||||
|
||||
loadRadialBarChart("totalUserRadialChart", data);
|
||||
|
||||
$(".chart-spinner").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
|
||||
function loadRadialBarChart(id, data) {
|
||||
var chartColors = getChartColorsArray(id);
|
||||
var options = {
|
||||
fill: {
|
||||
colors: chartColors
|
||||
},
|
||||
chart: {
|
||||
height: 90,
|
||||
width: 90,
|
||||
type: "radialBar",
|
||||
sparkline: {
|
||||
enabled: true
|
||||
},
|
||||
offsetY: -10,
|
||||
},
|
||||
series: data.series,
|
||||
plotOptions: {
|
||||
radialBar: {
|
||||
dataLabels: {
|
||||
value: {
|
||||
offsetY: -10,
|
||||
color: chartColors[0],
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
labels: [""]
|
||||
};
|
||||
var chart = new ApexCharts(document.querySelector("#" + id), options);
|
||||
chart.render();
|
||||
|
||||
}
|
||||
|
||||
|
||||
function getChartColorsArray(id) {
|
||||
if (document.getElementById(id) !== null) {
|
||||
var colors = document.getElementById(id).getAttribute("data-colors");
|
||||
if (colors) {
|
||||
colors = JSON.parse(colors);
|
||||
return colors.map(function (value) {
|
||||
var newValue = value.replace(" ", "");
|
||||
if (newValue.indexOf(",") === -1) {
|
||||
var color = getComputedStyle(document.documentElement).getPropertyValue(newValue);
|
||||
if (color) return color;
|
||||
else return newValue;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// Unobtrusive Ajax support library for jQuery
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// @version v3.2.6
|
||||
//
|
||||
// Microsoft grants you the right to use these script files for the sole
|
||||
// purpose of either: (i) interacting through your browser with the Microsoft
|
||||
// website or online service, subject to the applicable licensing or use
|
||||
// terms; or (ii) using the files as included with a Microsoft product subject
|
||||
// to that product's license terms. Microsoft reserves all other rights to the
|
||||
// files not expressly granted by Microsoft, whether by implication, estoppel
|
||||
// or otherwise. Insofar as a script file is dual licensed under GPL,
|
||||
// Microsoft neither took the code under GPL nor distributes it thereunder but
|
||||
// under the terms set out in this paragraph. All notices and licenses
|
||||
// below are for informational purposes only.
|
||||
!function(t){function a(t,a){for(var e=window,r=(t||"").split(".");e&&r.length;)e=e[r.shift()];return"function"==typeof e?e:(a.push(t),Function.constructor.apply(null,a))}function e(t){return"GET"===t||"POST"===t}function r(t,a){e(a)||t.setRequestHeader("X-HTTP-Method-Override",a)}function n(a,e,r){var n;r.indexOf("application/x-javascript")===-1&&(n=(a.getAttribute("data-ajax-mode")||"").toUpperCase(),t(a.getAttribute("data-ajax-update")).each(function(a,r){switch(n){case"BEFORE":t(r).prepend(e);break;case"AFTER":t(r).append(e);break;case"REPLACE-WITH":t(r).replaceWith(e);break;default:t(r).html(e)}}))}function i(i,u){var o,c,d,s;if(o=i.getAttribute("data-ajax-confirm"),!o||window.confirm(o)){c=t(i.getAttribute("data-ajax-loading")),s=parseInt(i.getAttribute("data-ajax-loading-duration"),10)||0,t.extend(u,{type:i.getAttribute("data-ajax-method")||void 0,url:i.getAttribute("data-ajax-url")||void 0,cache:"true"===(i.getAttribute("data-ajax-cache")||"").toLowerCase(),beforeSend:function(t){var e;return r(t,d),e=a(i.getAttribute("data-ajax-begin"),["xhr"]).apply(i,arguments),e!==!1&&c.show(s),e},complete:function(){c.hide(s),a(i.getAttribute("data-ajax-complete"),["xhr","status"]).apply(i,arguments)},success:function(t,e,r){n(i,t,r.getResponseHeader("Content-Type")||"text/html"),a(i.getAttribute("data-ajax-success"),["data","status","xhr"]).apply(i,arguments)},error:function(){a(i.getAttribute("data-ajax-failure"),["xhr","status","error"]).apply(i,arguments)}}),u.data.push({name:"X-Requested-With",value:"XMLHttpRequest"}),d=u.type.toUpperCase(),e(d)||(u.type="POST",u.data.push({name:"X-HTTP-Method-Override",value:d}));var p=t(i);if(p.is("form")&&"multipart/form-data"==p.attr("enctype")){var f=new FormData;t.each(u.data,function(t,a){f.append(a.name,a.value)}),t("input[type=file]",p).each(function(){var a=this;t.each(a.files,function(t,e){f.append(a.name,e)})}),t.extend(u,{processData:!1,contentType:!1,data:f})}t.ajax(u)}}function u(a){var e=t(a).data(d);return!e||!e.validate||e.validate()}var o="unobtrusiveAjaxClick",c="unobtrusiveAjaxClickTarget",d="unobtrusiveValidation";t(document).on("click","a[data-ajax=true]",function(t){t.preventDefault(),i(this,{url:this.href,type:"GET",data:[]})}),t(document).on("click","form[data-ajax=true] input[type=image]",function(a){var e=a.target.name,r=t(a.target),n=t(r.parents("form")[0]),i=r.offset();n.data(o,[{name:e+".x",value:Math.round(a.pageX-i.left)},{name:e+".y",value:Math.round(a.pageY-i.top)}]),setTimeout(function(){n.removeData(o)},0)}),t(document).on("click","form[data-ajax=true] :submit",function(a){var e=a.currentTarget.name,r=t(a.target),n=t(r.parents("form")[0]);n.data(o,e?[{name:e,value:a.currentTarget.value}]:[]),n.data(c,r),setTimeout(function(){n.removeData(o),n.removeData(c)},0)}),t(document).on("submit","form[data-ajax=true]",function(a){var e=t(this).data(o)||[],r=t(this).data(c),n=r&&(r.hasClass("cancel")||void 0!==r.attr("formnovalidate"));a.preventDefault(),(n||u(this))&&i(this,{url:this.action,type:this.method||"GET",data:e.concat(t(this).serializeArray())})})}(jQuery);
|
||||
@@ -0,0 +1,4 @@
|
||||
// Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification
|
||||
// for details on configuring this project to bundle and minify static web assets.
|
||||
|
||||
// Write your JavaScript code.
|
||||
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011-2021 Twitter, Inc.
|
||||
Copyright (c) 2011-2021 The Bootstrap Authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||