repository migration

This commit is contained in:
2025-05-20 11:46:50 -04:00
commit bf536b8774
213 changed files with 117679 additions and 0 deletions
+63
View File
@@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
+363
View File
@@ -0,0 +1,363 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
@@ -0,0 +1,14 @@
namespace WhiteLagoon.Web.ViewModels
{
public class LineChartDto
{
public List<ChartData> Series { get; set; }
public string[] Categories { get; set; }
}
public class ChartData
{
public string Name { get; set; }
public int[] Data { get; set; }
}
}
@@ -0,0 +1,8 @@
namespace WhiteLagoon.Web.ViewModels
{
public class PieChartDto
{
public decimal[] Series { get; set; }
public string[] Labels { get; set; }
}
}
@@ -0,0 +1,10 @@
namespace WhiteLagoon.Web.ViewModels
{
public class RadialBarChartDto
{
public decimal TotalCount { get; set; }
public decimal CountInCurrentMonth { get; set; }
public bool HasRatioIncreased { get; set; }
public int[] Series { get; set; }
}
}
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Domain.Entities;
namespace WhiteLagoon.Application.Common.Interfaces
{
public interface IAmenityRepository : IRepository<Amenity>
{
void Update(Amenity entity);
}
}
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Domain.Entities;
namespace WhiteLagoon.Application.Common.Interfaces
{
public interface IApplicationUserRepository : IRepository<ApplicationUser>
{
}
}
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Domain.Entities;
namespace WhiteLagoon.Application.Common.Interfaces
{
public interface IBookingRepository : IRepository<Booking>
{
void Update(Booking entity);
}
}
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WhiteLagoon.Application.Common.Interfaces
{
public interface IDbInitializer
{
void Initialize();
}
}
@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Domain.Entities;
namespace WhiteLagoon.Application.Common.Interfaces
{
public interface IRepository<T> where T : class
{
IEnumerable<T> GetAll(Expression<Func<T, bool>>? filter = null, string? includeProperties = null, bool tracked = false);
T Get(Expression<Func<T, bool>> filter, string? includeProperties = null, bool tracked = false);
void Add(T entity);
bool Any(Expression<Func<T, bool>> filter);
void Remove(T entity);
}
}
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WhiteLagoon.Application.Common.Interfaces
{
public interface IUnitOfWork
{
IVillaRepository Villa { get; }
IVillaNumberRepository VillaNumber { get; }
IBookingRepository Booking { get; }
IApplicationUserRepository User { get; }
IAmenityRepository Amenity { get; }
void Save();
}
}
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Domain.Entities;
namespace WhiteLagoon.Application.Common.Interfaces
{
public interface IVillaNumberRepository : IRepository<VillaNumber>
{
void Update(VillaNumber entity);
}
}
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Domain.Entities;
namespace WhiteLagoon.Application.Common.Interfaces
{
public interface IVillaRepository : IRepository<Villa>
{
void Update(Villa entity);
}
}
@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Domain.Entities;
using WhiteLagoon.Web.ViewModels;
namespace WhiteLagoon.Application.Common.Utility
{
public static class SD
{
public const string Role_Customer = "Customer";
public const string Role_Admin = "Admin";
public const string StatusPending = "Pending";
public const string StatusApproved = "Approved";
public const string StatusCheckedIn = "CheckedIn";
public const string StatusCompleted = "Completed";
public const string StatusCancelled = "Cancelled";
public const string StatusRefunded = "Refunded";
public static int VillaRoomsAvailable_Count(int villaId,
List<VillaNumber> villaNumberList, DateOnly checkInDate, int nights,
List<Booking> bookings)
{
List<int> bookingInDate = new();
int finalAvailableRoomForAllNights = int.MaxValue;
var roomsInVilla = villaNumberList.Where(x => x.VillaId == villaId).Count();
for(int i = 0; i < nights; i++)
{
var villasBooked = bookings.Where(u => u.CheckInDate <= checkInDate.AddDays(i)
&& u.CheckOutDate > checkInDate.AddDays(i) && u.VillaId == villaId);
foreach(var booking in villasBooked)
{
if (!bookingInDate.Contains(booking.Id))
{
bookingInDate.Add(booking.Id);
}
}
var totalAvailableRooms = roomsInVilla - bookingInDate.Count;
if(totalAvailableRooms == 0)
{
return 0;
}
else
{
if(finalAvailableRoomForAllNights > totalAvailableRooms)
{
finalAvailableRoomForAllNights = totalAvailableRooms;
}
}
}
return finalAvailableRoomForAllNights;
}
public static RadialBarChartDto GetRadialCartDataModel(int totalCount, double currentMonthCount, double prevMonthCount)
{
RadialBarChartDto RadialBarChartDto = new();
int increaseDecreaseRatio = 100;
if (prevMonthCount != 0)
{
increaseDecreaseRatio = Convert.ToInt32((currentMonthCount - prevMonthCount) / prevMonthCount * 100);
}
RadialBarChartDto.TotalCount = totalCount;
RadialBarChartDto.CountInCurrentMonth = Convert.ToInt32(currentMonthCount);
RadialBarChartDto.HasRatioIncreased = currentMonthCount > prevMonthCount;
RadialBarChartDto.Series = new int[] { increaseDecreaseRatio };
return RadialBarChartDto;
}
}
}
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WhiteLagoon.Application.Contract
{
public interface IEmailService
{
Task<bool> SendEmailAsync(string email, string subject, string message);
}
}
@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Application.Common.Interfaces;
using WhiteLagoon.Application.Services.Interface;
using WhiteLagoon.Domain.Entities;
namespace WhiteLagoon.Application.Services.Implementation
{
public class AmenityService : IAmenityService
{
private readonly IUnitOfWork _unitOfWork;
public AmenityService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public void CreateAmenity(Amenity amenity)
{
ArgumentNullException.ThrowIfNull(amenity);
_unitOfWork.Amenity.Add(amenity);
_unitOfWork.Save();
}
public bool DeleteAmenity(int id)
{
try
{
var amenity = _unitOfWork.Amenity.Get(u => u.Id == id);
if (amenity != null)
{
_unitOfWork.Amenity.Remove(amenity);
_unitOfWork.Save();
return true;
}
else
{
throw new InvalidOperationException($"Amenity with ID {id} not found.");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return false;
}
public IEnumerable<Amenity> GetAllAmenities()
{
return _unitOfWork.Amenity.GetAll(includeProperties: "Villa");
}
public Amenity GetAmenityById(int id)
{
return _unitOfWork.Amenity.Get(u => u.Id == id, includeProperties: "Villa");
}
public void UpdateAmenity(Amenity amenity)
{
ArgumentNullException.ThrowIfNull(amenity);
_unitOfWork.Amenity.Update(amenity);
_unitOfWork.Save();
}
}
}
@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Application.Common.Interfaces;
using WhiteLagoon.Application.Common.Utility;
using WhiteLagoon.Application.Services.Interface;
using WhiteLagoon.Domain.Entities;
namespace WhiteLagoon.Application.Services.Implementation
{
public class BookingService : IBookingService
{
private readonly IUnitOfWork _unitOfWork;
public BookingService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public void CreateBooking(Booking booking)
{
_unitOfWork.Booking.Add(booking);
_unitOfWork.Save();
}
public IEnumerable<Booking> GetAllBookings(string userId = "", string? statusFilterList = "")
{
IEnumerable<string> statusList = statusFilterList.ToLower().Split(",");
if(!string.IsNullOrEmpty(statusFilterList) && !string.IsNullOrEmpty(userId))
{
return _unitOfWork.Booking.GetAll(u => statusList.Contains(u.Status.ToLower()) &&
u.UserId == userId, includeProperties: "User,Villa");
}
else
{
if (!string.IsNullOrEmpty(statusFilterList))
{
return _unitOfWork.Booking.GetAll(u => statusList.Contains(u.Status.ToLower()), includeProperties: "User,Villa");
}
if (!string.IsNullOrEmpty(userId))
{
return _unitOfWork.Booking.GetAll(u => u.UserId == userId, includeProperties: "User,Villa");
}
}
return _unitOfWork.Booking.GetAll(includeProperties: "User, Villa");
}
public Booking GetBookingById(int bookingId)
{
return _unitOfWork.Booking.Get(u=>u.Id==bookingId,includeProperties: "User, Villa");
}
public IEnumerable<int> GetCheckedInVillaNumbers(int villaId)
{
return _unitOfWork.Booking.GetAll(u => u.VillaId == villaId && u.Status == SD.StatusCheckedIn)
.Select(u => u.VillaNumber);
}
public void UpdateStatus(int bookingId, string bookingStatus, int villaNumber = 0)
{
var bookingFromDb = _unitOfWork.Booking.Get(m => m.Id == bookingId, tracked:true);
if (bookingFromDb != null)
{
bookingFromDb.Status = bookingStatus;
if (bookingStatus == SD.StatusCheckedIn)
{
bookingFromDb.VillaNumber = villaNumber;
bookingFromDb.ActualCheckInDate = DateTime.Now;
}
if (bookingStatus == SD.StatusCompleted)
{
bookingFromDb.ActualCheckOutDate = DateTime.Now;
}
}
_unitOfWork.Save();
}
public void UpdateStripePaymentID(int bookingId, string sessionId, string paymentIntentId)
{
var bookingFromDb = _unitOfWork.Booking.Get(m => m.Id == bookingId, tracked: true);
if (bookingFromDb != null)
{
if (!string.IsNullOrEmpty(sessionId))
{
bookingFromDb.StripeSessionId = sessionId;
}
if (!string.IsNullOrEmpty(paymentIntentId))
{
bookingFromDb.StripePaymentIntentId = paymentIntentId;
bookingFromDb.PaymentDate = DateTime.Now;
bookingFromDb.IsPaymentSuccessful = true;
}
}
_unitOfWork.Save();
}
}
}
@@ -0,0 +1,156 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Application.Common.Interfaces;
using WhiteLagoon.Application.Common.Utility;
using WhiteLagoon.Application.Services.Interface;
using WhiteLagoon.Web.ViewModels;
namespace WhiteLagoon.Application.Services.Implementation
{
public class DashboardService : IDashboardService
{
private readonly IUnitOfWork _unitOfWork;
static int previousMonth = DateTime.Now.Month == 1 ? 12 : DateTime.Now.Month - 1;
readonly DateTime previousMonthStartDate = new(DateTime.Now.Year, previousMonth, 1);
readonly DateTime currentMonthStartDate = new(DateTime.Now.Year, DateTime.Now.Month, 1);
public DashboardService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public async Task<PieChartDto> GetBookingPieChartData()
{
var totalBookings = _unitOfWork.Booking.GetAll(u => u.BookingDate >= DateTime.Now.AddDays(-30) &&
(u.Status != SD.StatusPending || u.Status == SD.StatusCancelled));
var customerWithOneBooking = totalBookings.GroupBy(b => b.UserId).Where(x => x.Count() == 1).Select(x => x.Key).ToList();
int bookingsByNewCustomer = customerWithOneBooking.Count();
int bookingsByReturningCustomer = totalBookings.Count() - bookingsByNewCustomer;
PieChartDto PieChartDto = new()
{
Labels = new string[] { "New Customer Bookings", "Returning Customer Bookings" },
Series = new decimal[] { bookingsByNewCustomer, bookingsByReturningCustomer }
};
return PieChartDto;
}
public async Task<LineChartDto> GetMemberAndBookingLineChartData()
{
var bookingData = _unitOfWork.Booking.GetAll(u => u.BookingDate >= DateTime.Now.AddDays(-30) &&
u.BookingDate.Date <= DateTime.Now)
.GroupBy(b => b.BookingDate.Date)
.Select(u => new {
DateTime = u.Key,
NewBookingCount = u.Count()
});
var customerData = _unitOfWork.User.GetAll(u => u.CreatedAt >= DateTime.Now.AddDays(-30) &&
u.CreatedAt.Date <= DateTime.Now)
.GroupBy(b => b.CreatedAt.Date)
.Select(u => new {
DateTime = u.Key,
NewCustomerCount = u.Count()
});
var leftJoin = bookingData.GroupJoin(customerData, booking => booking.DateTime, customer => customer.DateTime,
(booking, customer) => new
{
booking.DateTime,
booking.NewBookingCount,
NewCustomerCount = customer.Select(x => x.NewCustomerCount).FirstOrDefault()
});
var rightJoin = customerData.GroupJoin(bookingData, customer => customer.DateTime, booking => booking.DateTime,
(customer, booking) => new
{
customer.DateTime,
NewBookingCount = booking.Select(x => x.NewBookingCount).FirstOrDefault(),
customer.NewCustomerCount
});
var mergedData = leftJoin.Union(rightJoin).OrderBy(x => x.DateTime).ToList();
var newBookingData = mergedData.Select(x => x.NewBookingCount).ToArray();
var newCustomerData = mergedData.Select(x => x.NewCustomerCount).ToArray();
var categories = mergedData.Select(x => x.DateTime.ToString("MM/dd/yyyy")).ToArray();
List<ChartData> chartDataList = new()
{
new ChartData
{
Name = "New Bookings",
Data = newBookingData
},
new ChartData
{
Name = "New Members",
Data = newCustomerData
},
};
LineChartDto LineChartDto = new()
{
Categories = categories,
Series = chartDataList
};
return LineChartDto;
}
public async Task<RadialBarChartDto> GetRegisteredUserChartData()
{
var totalUsers = _unitOfWork.User.GetAll();
var countByCurrentMonth = totalUsers.Count(u => u.CreatedAt >= currentMonthStartDate &&
u.CreatedAt <= DateTime.Now);
var countByPreviousMonth = totalUsers.Count(u => u.CreatedAt >= previousMonthStartDate &&
u.CreatedAt <= currentMonthStartDate);
return SD.GetRadialCartDataModel(totalUsers.Count(), countByCurrentMonth, countByPreviousMonth);
}
public async Task<RadialBarChartDto> GetRevenueChartData()
{
var totalBookings = _unitOfWork.Booking.GetAll(u => u.Status != SD.StatusPending
|| u.Status == SD.StatusCancelled);
var totalRevenue = Convert.ToInt32(totalBookings.Sum(u => u.TotalCost));
var countByCurrentMonth = totalBookings.Where(u => u.BookingDate >= currentMonthStartDate &&
u.BookingDate <= DateTime.Now).Sum(u => u.TotalCost);
var countByPreviousMonth = totalBookings.Where(u => u.BookingDate >= previousMonthStartDate &&
u.BookingDate <= currentMonthStartDate).Sum(u => u.TotalCost);
return SD.GetRadialCartDataModel(totalRevenue, countByCurrentMonth, countByPreviousMonth);
}
public async Task<RadialBarChartDto> GetTotalBookingRadialChartData()
{
var totalBookings = _unitOfWork.Booking.GetAll(u => u.Status != SD.StatusPending
|| u.Status == SD.StatusCancelled);
var countByCurrentMonth = totalBookings.Count(u => u.BookingDate >= currentMonthStartDate &&
u.BookingDate <= DateTime.Now);
var countByPreviousMonth = totalBookings.Count(u => u.BookingDate >= previousMonthStartDate &&
u.BookingDate <= currentMonthStartDate);
return SD.GetRadialCartDataModel(totalBookings.Count(), countByCurrentMonth, countByPreviousMonth);
}
}
}
@@ -0,0 +1,50 @@
using Stripe.Checkout;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Application.Services.Interface;
using WhiteLagoon.Domain.Entities;
namespace WhiteLagoon.Application.Services.Implementation
{
public class PaymentService : IPaymentService
{
public Session CreateStripeSession(SessionCreateOptions options)
{
var service = new SessionService();
Session session = service.Create(options);
return session;
}
public SessionCreateOptions CreateStripeSessionOptions(Booking booking, Villa villa, string domain)
{
var options = new SessionCreateOptions
{
LineItems = new List<SessionLineItemOptions>(),
Mode = "payment",
SuccessUrl = domain + $"booking/BookingConfirmation?bookingId={booking.Id}",
CancelUrl = domain + $"booking/FinalizeBooking?villaId={booking.VillaId}&checkInDate={booking.CheckInDate}&nights={booking.Nights}",
};
options.LineItems.Add(new SessionLineItemOptions
{
PriceData = new SessionLineItemPriceDataOptions
{
UnitAmount = (long)(booking.TotalCost * 100),
Currency = "usd",
ProductData = new SessionLineItemPriceDataProductDataOptions
{
Name = villa.Name
//Images = new List<string> { domain + villa.ImageUrl },
},
},
Quantity = 1,
});
return options;
}
}
}
@@ -0,0 +1,68 @@
using Microsoft.AspNetCore.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Application.Common.Interfaces;
using WhiteLagoon.Application.Services.Interface;
using WhiteLagoon.Domain.Entities;
namespace WhiteLagoon.Application.Services.Implementation
{
public class VillaNumberService : IVillaNumberService
{
private readonly IUnitOfWork _unitOfWork;
public VillaNumberService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public bool CheckVillaNumberExists(int villa_Number)
{
return _unitOfWork.VillaNumber.Any(u => u.Villa_Number == villa_Number);
}
public void CreateVillaNumber(VillaNumber villaNumber)
{
_unitOfWork.VillaNumber.Add(villaNumber);
_unitOfWork.Save();
}
public bool DeleteVillaNumber(int id)
{
try
{
VillaNumber? objFromDb = _unitOfWork.VillaNumber.Get(u => u.Villa_Number == id);
if (objFromDb is not null)
{
_unitOfWork.VillaNumber.Remove(objFromDb);
_unitOfWork.Save();
return true;
}
return false;
}
catch (Exception)
{
return false;
}
}
public IEnumerable<VillaNumber> GetAllVillaNumbers()
{
return _unitOfWork.VillaNumber.GetAll(includeProperties: "Villa");
}
public VillaNumber GetVillaNumberById(int id)
{
return _unitOfWork.VillaNumber.Get(u => u.Villa_Number == id, includeProperties: "Villa");
}
public void UpdateVillaNumber(VillaNumber villaNumber)
{
_unitOfWork.VillaNumber.Update(villaNumber);
_unitOfWork.Save();
}
}
}
@@ -0,0 +1,143 @@
using Microsoft.AspNetCore.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Application.Common.Interfaces;
using WhiteLagoon.Application.Common.Utility;
using WhiteLagoon.Application.Services.Interface;
using WhiteLagoon.Domain.Entities;
namespace WhiteLagoon.Application.Services.Implementation
{
public class VillaService : IVillaService
{
private readonly IUnitOfWork _unitOfWork;
private readonly IWebHostEnvironment _webHostEnvironment;
public VillaService(IUnitOfWork unitOfWork, IWebHostEnvironment webHostEnvironment)
{
_unitOfWork = unitOfWork;
_webHostEnvironment = webHostEnvironment;
}
public void CreateVilla(Villa villa)
{
if (villa.Image != null)
{
string fileName = Guid.NewGuid().ToString() + Path.GetExtension(villa.Image.FileName);
string imagePath = Path.Combine(_webHostEnvironment.WebRootPath, @"images\VillaImage");
using var fileStream = new FileStream(Path.Combine(imagePath, fileName), FileMode.Create);
villa.Image.CopyTo(fileStream);
villa.ImageUrl = @"\images\VillaImage\" + fileName;
}
else
{
villa.ImageUrl = "https://placehold.co/600x400";
}
_unitOfWork.Villa.Add(villa);
_unitOfWork.Save();
}
public bool DeleteVilla(int id)
{
try
{
Villa? objFromDb = _unitOfWork.Villa.Get(u => u.Id == id);
if (objFromDb is not null)
{
if (!string.IsNullOrEmpty(objFromDb.ImageUrl))
{
var oldImagePath = Path.Combine(_webHostEnvironment.WebRootPath, objFromDb.ImageUrl.TrimStart('\\'));
if (System.IO.File.Exists(oldImagePath))
{
System.IO.File.Delete(oldImagePath);
}
}
_unitOfWork.Villa.Remove(objFromDb);
_unitOfWork.Save();
}
return true;
}
catch (Exception)
{
return false;
}
}
public IEnumerable<Villa> GetAllVillas()
{
return _unitOfWork.Villa.GetAll(includeProperties: "VillaAmenity");
}
public Villa GetVillaById(int id)
{
return _unitOfWork.Villa.Get(u => u.Id == id, includeProperties: "VillaAmenity");
}
public IEnumerable<Villa> GetVillasAvailabilityByDate(int nights, DateOnly checkInDate)
{
var villaList = _unitOfWork.Villa.GetAll(includeProperties: "VillaAmenity").ToList();
var villaNumbersList = _unitOfWork.VillaNumber.GetAll().ToList();
var bookedVillas = _unitOfWork.Booking.GetAll(u => u.Status == SD.StatusApproved ||
u.Status == SD.StatusCheckedIn).ToList();
foreach (var villa in villaList)
{
int roomAvailable = SD.VillaRoomsAvailable_Count
(villa.Id, villaNumbersList, checkInDate, nights, bookedVillas);
villa.IsAvailable = roomAvailable > 0 ? true : false;
}
return villaList;
}
public bool IsVillaAvailableByDate(int villaId, int nights, DateOnly checkInDate)
{
var villaNumbersList = _unitOfWork.VillaNumber.GetAll().ToList();
var bookedVillas = _unitOfWork.Booking.GetAll(u => u.Status == SD.StatusApproved ||
u.Status == SD.StatusCheckedIn).ToList();
int roomAvailable = SD.VillaRoomsAvailable_Count
(villaId, villaNumbersList, checkInDate, nights, bookedVillas);
return roomAvailable > 0;
}
public void UpdateVilla(Villa villa)
{
if (villa.Image != null)
{
string fileName = Guid.NewGuid().ToString() + Path.GetExtension(villa.Image.FileName);
string imagePath = Path.Combine(_webHostEnvironment.WebRootPath, @"images\VillaImage");
if (!string.IsNullOrEmpty(villa.ImageUrl))
{
var oldImagePath = Path.Combine(_webHostEnvironment.WebRootPath, villa.ImageUrl.TrimStart('\\'));
if (System.IO.File.Exists(oldImagePath))
{
System.IO.File.Delete(oldImagePath);
}
}
using var fileStream = new FileStream(Path.Combine(imagePath, fileName), FileMode.Create);
villa.Image.CopyTo(fileStream);
villa.ImageUrl = @"\images\VillaImage\" + fileName;
}
_unitOfWork.Villa.Update(villa);
_unitOfWork.Save();
}
}
}
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Domain.Entities;
namespace WhiteLagoon.Application.Services.Interface
{
public interface IAmenityService
{
IEnumerable<Amenity> GetAllAmenities();
void CreateAmenity(Amenity amenity);
void UpdateAmenity(Amenity amenity);
Amenity GetAmenityById(int id);
bool DeleteAmenity(int id);
}
}
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Domain.Entities;
namespace WhiteLagoon.Application.Services.Interface
{
public interface IBookingService
{
void CreateBooking(Booking booking);
Booking GetBookingById(int bookingId);
IEnumerable<Booking> GetAllBookings(string userId="",string? statusFilterList="");
void UpdateStatus(int bookingId, string bookingStatus, int villaNumber);
void UpdateStripePaymentID(int bookingId, string sessionId, string paymentIntentId);
public IEnumerable<int> GetCheckedInVillaNumbers(int villaId);
}
}
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Web.ViewModels;
namespace WhiteLagoon.Application.Services.Interface
{
public interface IDashboardService
{
Task<RadialBarChartDto> GetTotalBookingRadialChartData();
Task<RadialBarChartDto> GetRegisteredUserChartData();
Task<RadialBarChartDto> GetRevenueChartData();
Task<PieChartDto> GetBookingPieChartData();
Task<LineChartDto> GetMemberAndBookingLineChartData();
}
}
@@ -0,0 +1,17 @@
using Stripe.Checkout;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Domain.Entities;
namespace WhiteLagoon.Application.Services.Interface
{
public interface IPaymentService
{
SessionCreateOptions CreateStripeSessionOptions(Booking booking, Villa villa, string domain);
Session CreateStripeSession(SessionCreateOptions options);
}
}
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Domain.Entities;
namespace WhiteLagoon.Application.Services.Interface
{
public interface IVillaNumberService
{
IEnumerable<VillaNumber> GetAllVillaNumbers();
VillaNumber GetVillaNumberById(int id);
void CreateVillaNumber(VillaNumber villaNumber);
void UpdateVillaNumber(VillaNumber villaNumber);
bool DeleteVillaNumber(int id);
bool CheckVillaNumberExists(int villa_Number);
}
}
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Domain.Entities;
namespace WhiteLagoon.Application.Services.Interface
{
public interface IVillaService
{
IEnumerable<Villa> GetAllVillas();
Villa GetVillaById(int id);
void CreateVilla(Villa villa);
void UpdateVilla(Villa villa);
bool DeleteVilla(int id);
IEnumerable<Villa> GetVillasAvailabilityByDate(int nights, DateOnly checkInDate);
bool IsVillaAvailableByDate(int villaId, int nights, DateOnly checkInDate);
}
}
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Stripe.net" Version="41.27.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WhiteLagoon.Domain\WhiteLagoon.Domain.csproj" />
</ItemGroup>
</Project>
+27
View File
@@ -0,0 +1,27 @@
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WhiteLagoon.Domain.Entities
{
public class Amenity
{
[Key]
public int Id { get; set; }
public required string Name { get; set; }
public string? Description { get; set; }
[ForeignKey("Villa")]
public int VillaId { get; set; }
[ValidateNever]
public Villa Villa { get; set; }
}
}
@@ -0,0 +1,15 @@
using Microsoft.AspNetCore.Identity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WhiteLagoon.Domain.Entities
{
public class ApplicationUser : IdentityUser
{
public string Name { get; set; }
public DateTime CreatedAt { get; set; }
}
}
+59
View File
@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WhiteLagoon.Domain.Entities
{
public class Booking
{
[Key]
public int Id { get; set; }
[Required]
public string UserId { get; set; }
[ForeignKey("UserId")]
public ApplicationUser User { get; set; }
[Required]
public int VillaId { get; set; }
[ForeignKey("VillaId")]
public Villa Villa { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Email { get; set; }
public string? Phone { get; set; }
[Required]
public double TotalCost { get; set; }
public int Nights { get; set; }
public string? Status { get; set; }
[Required]
public DateTime BookingDate { get; set; }
[Required]
public DateOnly CheckInDate { get; set; }
[Required]
public DateOnly CheckOutDate { get; set; }
public bool IsPaymentSuccessful { get; set; } = false;
public DateTime PaymentDate { get; set; }
public string? StripeSessionId { get; set; }
public string? StripePaymentIntentId { get; set; }
public DateTime ActualCheckInDate { get; set; }
public DateTime ActualCheckOutDate { get; set; }
public int VillaNumber { get; set; }
[NotMapped]
public List<VillaNumber> VillaNumbers { get; set; }
}
}
+38
View File
@@ -0,0 +1,38 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WhiteLagoon.Domain.Entities
{
public class Villa
{
public int Id { get; set; }
[MaxLength(50)]
public required string Name { get; set; }
public string? Description { get; set; }
[Display(Name = "Price per night")]
[Range(10, 10000)]
public double Price { get; set; }
public int Sqft { get; set; }
[Range(1, 10)]
public int Occupancy { get; set; }
[NotMapped]
public IFormFile? Image { get; set; }
[Display(Name = "Image Url")]
public string? ImageUrl { get; set; }
public DateTime? Created_Date { get; set; }
public DateTime? Updated_Date { get; set; }
[ValidateNever]
public IEnumerable<Amenity> VillaAmenity { get; set; }
[NotMapped]
public bool IsAvailable { get; set; } = true;
}
}
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
namespace WhiteLagoon.Domain.Entities
{
public class VillaNumber
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Villa Number")]
public int Villa_Number { get; set; }
[ForeignKey("Villa")]
public int VillaId { get; set; }
[ValidateNever]
public Villa Villa { get; set; }
public string? SpecialDetails { get; set; }
}
}
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
</Project>
@@ -0,0 +1,171 @@
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Domain.Entities;
namespace WhiteLagoon.Infrastructure.Data
{
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
public DbSet<Villa> Villas { get; set; }
public DbSet<VillaNumber> VillaNumbers { get; set; }
public DbSet<Amenity> Amenities { get; set; }
public DbSet<ApplicationUser> ApplicationUsers { get; set; }
public DbSet<Booking> Bookings { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Villa>().HasData(
new Villa
{
Id = 1,
Name = "Royal Villa",
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x400",
Occupancy = 4,
Price = 200,
Sqft = 550,
},
new Villa
{
Id = 2,
Name = "Premium Pool Villa",
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x401",
Occupancy = 4,
Price = 300,
Sqft = 550,
},
new Villa
{
Id = 3,
Name = "Luxury Pool Villa",
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x402",
Occupancy = 4,
Price = 400,
Sqft = 750,
});
modelBuilder.Entity<VillaNumber>().HasData(
new VillaNumber
{
Villa_Number = 101,
VillaId = 1,
},
new VillaNumber
{
Villa_Number = 102,
VillaId = 1,
},
new VillaNumber
{
Villa_Number = 103,
VillaId = 1,
},
new VillaNumber
{
Villa_Number = 104,
VillaId = 1,
},
new VillaNumber
{
Villa_Number = 201,
VillaId = 2,
},
new VillaNumber
{
Villa_Number = 202,
VillaId = 2,
},
new VillaNumber
{
Villa_Number = 203,
VillaId = 2,
},
new VillaNumber
{
Villa_Number = 301,
VillaId = 3,
},
new VillaNumber
{
Villa_Number = 302,
VillaId = 3,
}
);
modelBuilder.Entity<Amenity>().HasData(
new Amenity
{
Id = 1,
VillaId = 1,
Name = "Private Pool"
}, new Amenity
{
Id = 2,
VillaId = 1,
Name = "Microwave"
}, new Amenity
{
Id = 3,
VillaId = 1,
Name = "Private Balcony"
}, new Amenity
{
Id = 4,
VillaId = 1,
Name = "1 king bed and 1 sofa bed"
},
new Amenity
{
Id = 5,
VillaId = 2,
Name = "Private Plunge Pool"
}, new Amenity
{
Id = 6,
VillaId = 2,
Name = "Microwave and Mini Refrigerator"
}, new Amenity
{
Id = 7,
VillaId = 2,
Name = "Private Balcony"
}, new Amenity
{
Id = 8,
VillaId = 2,
Name = "king bed or 2 double beds"
},
new Amenity
{
Id = 9,
VillaId = 3,
Name = "Private Pool"
}, new Amenity
{
Id = 10,
VillaId = 3,
Name = "Jacuzzi"
}, new Amenity
{
Id = 11,
VillaId = 3,
Name = "Private Balcony"
});
}
}
}
@@ -0,0 +1,64 @@
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Application.Common.Interfaces;
using WhiteLagoon.Application.Common.Utility;
using WhiteLagoon.Domain.Entities;
namespace WhiteLagoon.Infrastructure.Data
{
public class DbInitializer : IDbInitializer
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly RoleManager<IdentityRole> _roleManager;
private readonly ApplicationDbContext _db;
public DbInitializer(
UserManager<ApplicationUser> userManager,
RoleManager<IdentityRole> roleManager,
ApplicationDbContext db)
{
_roleManager = roleManager;
_userManager = userManager;
_db = db;
}
public void Initialize()
{
try
{
if (_db.Database.GetPendingMigrations().Count() > 0)
{
_db.Database.Migrate();
}
if (!_roleManager.RoleExistsAsync(SD.Role_Admin).GetAwaiter().GetResult())
{
_roleManager.CreateAsync(new IdentityRole(SD.Role_Admin)).Wait();
_roleManager.CreateAsync(new IdentityRole(SD.Role_Customer)).Wait();
_userManager.CreateAsync(new ApplicationUser
{
UserName = "admin@dotnetmastery.com",
Email = "admin@dotnetmastery.com",
Name = "Bhrugen Patel",
NormalizedUserName = "ADMIN@DOTNETMASTERY.COM",
NormalizedEmail = "ADMIN@DOTNETMASTERY.COM",
PhoneNumber = "1112223333",
}, "Admin123*").GetAwaiter().GetResult();
ApplicationUser user = _db.ApplicationUsers.FirstOrDefault(u => u.Email == "admin@dotnetmastery.com");
_userManager.AddToRoleAsync(user, SD.Role_Admin).GetAwaiter().GetResult();
}
}
catch (Exception e)
{
throw;
}
}
}
}
@@ -0,0 +1,38 @@
using Microsoft.Extensions.Configuration;
using SendGrid;
using SendGrid.Helpers.Mail;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Mail;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Application.Contract;
namespace WhiteLagoon.Infrastructure.Emails
{
public class EmailService : IEmailService
{
private readonly string _sendGridKey;
public EmailService(IConfiguration configuration)
{
_sendGridKey = configuration["SendGrid:Key"];
}
public async Task<bool> SendEmailAsync(string email, string subject, string message)
{
var client = new SendGridClient(_sendGridKey);
var from = new EmailAddress("hello@dotnetmastery.com", "DotNetMastery - White Lagoon");
var to = new EmailAddress(email);
var msg = MailHelper.CreateSingleEmail(from, to, subject, "", message);
var response = await client.SendEmailAsync(msg);
if (response.StatusCode == System.Net.HttpStatusCode.Accepted || response.StatusCode == System.Net.HttpStatusCode.OK)
{
return true;
}
return false;
}
}
}
@@ -0,0 +1,68 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using WhiteLagoon.Infrastructure.Data;
#nullable disable
namespace WhiteLagoon.Infrastructure.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20230804001201_AddVillaToDb")]
partial class AddVillaToDb
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0-preview.6.23329.4")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Villa", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime?>("CreatedDate")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("ImageUrl")
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("Occupancy")
.HasColumnType("int");
b.Property<double>("Price")
.HasColumnType("float");
b.Property<int>("Sqft")
.HasColumnType("int");
b.Property<DateTime?>("UpdatedDate")
.HasColumnType("datetime2");
b.HasKey("Id");
b.ToTable("Villas");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,42 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace WhiteLagoon.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class AddVillaToDb : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Villas",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Name = table.Column<string>(type: "nvarchar(max)", nullable: false),
Description = table.Column<string>(type: "nvarchar(max)", nullable: true),
Price = table.Column<double>(type: "float", nullable: false),
Sqft = table.Column<int>(type: "int", nullable: false),
Occupancy = table.Column<int>(type: "int", nullable: false),
ImageUrl = table.Column<string>(type: "nvarchar(max)", nullable: true),
CreatedDate = table.Column<DateTime>(type: "datetime2", nullable: true),
UpdatedDate = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Villas", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Villas");
}
}
}
@@ -0,0 +1,68 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using WhiteLagoon.Infrastructure.Data;
#nullable disable
namespace WhiteLagoon.Infrastructure.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20230804001243_ModfiyNamesInVillaTable")]
partial class ModfiyNamesInVillaTable
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0-preview.6.23329.4")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Villa", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime?>("Created_Date")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("ImageUrl")
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("Occupancy")
.HasColumnType("int");
b.Property<double>("Price")
.HasColumnType("float");
b.Property<int>("Sqft")
.HasColumnType("int");
b.Property<DateTime?>("Updated_Date")
.HasColumnType("datetime2");
b.HasKey("Id");
b.ToTable("Villas");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,38 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace WhiteLagoon.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class ModfiyNamesInVillaTable : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "UpdatedDate",
table: "Villas",
newName: "Updated_Date");
migrationBuilder.RenameColumn(
name: "CreatedDate",
table: "Villas",
newName: "Created_Date");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "Updated_Date",
table: "Villas",
newName: "UpdatedDate");
migrationBuilder.RenameColumn(
name: "Created_Date",
table: "Villas",
newName: "CreatedDate");
}
}
}
@@ -0,0 +1,100 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using WhiteLagoon.Infrastructure.Data;
#nullable disable
namespace WhiteLagoon.Infrastructure.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20230804001325_seedVillaToDb")]
partial class seedVillaToDb
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0-preview.6.23329.4")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Villa", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime?>("Created_Date")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("ImageUrl")
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("Occupancy")
.HasColumnType("int");
b.Property<double>("Price")
.HasColumnType("float");
b.Property<int>("Sqft")
.HasColumnType("int");
b.Property<DateTime?>("Updated_Date")
.HasColumnType("datetime2");
b.HasKey("Id");
b.ToTable("Villas");
b.HasData(
new
{
Id = 1,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x400",
Name = "Royal Villa",
Occupancy = 4,
Price = 200.0,
Sqft = 550
},
new
{
Id = 2,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x401",
Name = "Premium Pool Villa",
Occupancy = 4,
Price = 300.0,
Sqft = 550
},
new
{
Id = 3,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x402",
Name = "Luxury Pool Villa",
Occupancy = 4,
Price = 400.0,
Sqft = 750
});
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,45 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace WhiteLagoon.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class seedVillaToDb : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.InsertData(
table: "Villas",
columns: new[] { "Id", "Created_Date", "Description", "ImageUrl", "Name", "Occupancy", "Price", "Sqft", "Updated_Date" },
values: new object[,]
{
{ 1, null, "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.", "https://placehold.co/600x400", "Royal Villa", 4, 200.0, 550, null },
{ 2, null, "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.", "https://placehold.co/600x401", "Premium Pool Villa", 4, 300.0, 550, null },
{ 3, null, "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.", "https://placehold.co/600x402", "Luxury Pool Villa", 4, 400.0, 750, null }
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "Villas",
keyColumn: "Id",
keyValue: 1);
migrationBuilder.DeleteData(
table: "Villas",
keyColumn: "Id",
keyValue: 2);
migrationBuilder.DeleteData(
table: "Villas",
keyColumn: "Id",
keyValue: 3);
}
}
}
@@ -0,0 +1,177 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using WhiteLagoon.Infrastructure.Data;
#nullable disable
namespace WhiteLagoon.Infrastructure.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20230804004347_addVillaNumber")]
partial class addVillaNumber
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0-preview.6.23329.4")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Villa", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime?>("Created_Date")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("ImageUrl")
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<int>("Occupancy")
.HasColumnType("int");
b.Property<double>("Price")
.HasColumnType("float");
b.Property<int>("Sqft")
.HasColumnType("int");
b.Property<DateTime?>("Updated_Date")
.HasColumnType("datetime2");
b.HasKey("Id");
b.ToTable("Villas");
b.HasData(
new
{
Id = 1,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x400",
Name = "Royal Villa",
Occupancy = 4,
Price = 200.0,
Sqft = 550
},
new
{
Id = 2,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x401",
Name = "Premium Pool Villa",
Occupancy = 4,
Price = 300.0,
Sqft = 550
},
new
{
Id = 3,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x402",
Name = "Luxury Pool Villa",
Occupancy = 4,
Price = 400.0,
Sqft = 750
});
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.VillaNumber", b =>
{
b.Property<int>("Villa_Number")
.HasColumnType("int");
b.Property<string>("SpecialDetails")
.HasColumnType("nvarchar(max)");
b.Property<int>("VillaId")
.HasColumnType("int");
b.HasKey("Villa_Number");
b.HasIndex("VillaId");
b.ToTable("VillaNumbers");
b.HasData(
new
{
Villa_Number = 101,
VillaId = 1
},
new
{
Villa_Number = 102,
VillaId = 1
},
new
{
Villa_Number = 103,
VillaId = 1
},
new
{
Villa_Number = 104,
VillaId = 1
},
new
{
Villa_Number = 201,
VillaId = 2
},
new
{
Villa_Number = 202,
VillaId = 2
},
new
{
Villa_Number = 203,
VillaId = 2
},
new
{
Villa_Number = 301,
VillaId = 3
},
new
{
Villa_Number = 302,
VillaId = 3
});
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.VillaNumber", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.Villa", "Villa")
.WithMany()
.HasForeignKey("VillaId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Villa");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,81 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace WhiteLagoon.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class addVillaNumber : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "Name",
table: "Villas",
type: "nvarchar(50)",
maxLength: 50,
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.CreateTable(
name: "VillaNumbers",
columns: table => new
{
Villa_Number = table.Column<int>(type: "int", nullable: false),
VillaId = table.Column<int>(type: "int", nullable: false),
SpecialDetails = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_VillaNumbers", x => x.Villa_Number);
table.ForeignKey(
name: "FK_VillaNumbers_Villas_VillaId",
column: x => x.VillaId,
principalTable: "Villas",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.InsertData(
table: "VillaNumbers",
columns: new[] { "Villa_Number", "SpecialDetails", "VillaId" },
values: new object[,]
{
{ 101, null, 1 },
{ 102, null, 1 },
{ 103, null, 1 },
{ 104, null, 1 },
{ 201, null, 2 },
{ 202, null, 2 },
{ 203, null, 2 },
{ 301, null, 3 },
{ 302, null, 3 }
});
migrationBuilder.CreateIndex(
name: "IX_VillaNumbers_VillaId",
table: "VillaNumbers",
column: "VillaId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "VillaNumbers");
migrationBuilder.AlterColumn<string>(
name: "Name",
table: "Villas",
type: "nvarchar(max)",
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(50)",
oldMaxLength: 50);
}
}
}
@@ -0,0 +1,281 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using WhiteLagoon.Infrastructure.Data;
#nullable disable
namespace WhiteLagoon.Infrastructure.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20230804193317_AddAmenityToDb")]
partial class AddAmenityToDb
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0-preview.6.23329.4")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Amenity", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("VillaId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("VillaId");
b.ToTable("Amenities");
b.HasData(
new
{
Id = 1,
Name = "Private Pool",
VillaId = 1
},
new
{
Id = 2,
Name = "Microwave",
VillaId = 1
},
new
{
Id = 3,
Name = "Private Balcony",
VillaId = 1
},
new
{
Id = 4,
Name = "1 king bed and 1 sofa bed",
VillaId = 1
},
new
{
Id = 5,
Name = "Private Plunge Pool",
VillaId = 2
},
new
{
Id = 6,
Name = "Microwave and Mini Refrigerator",
VillaId = 2
},
new
{
Id = 7,
Name = "Private Balcony",
VillaId = 2
},
new
{
Id = 8,
Name = "king bed or 2 double beds",
VillaId = 2
},
new
{
Id = 9,
Name = "Private Pool",
VillaId = 3
},
new
{
Id = 10,
Name = "Jacuzzi",
VillaId = 3
},
new
{
Id = 11,
Name = "Private Balcony",
VillaId = 3
});
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Villa", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime?>("Created_Date")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("ImageUrl")
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<int>("Occupancy")
.HasColumnType("int");
b.Property<double>("Price")
.HasColumnType("float");
b.Property<int>("Sqft")
.HasColumnType("int");
b.Property<DateTime?>("Updated_Date")
.HasColumnType("datetime2");
b.HasKey("Id");
b.ToTable("Villas");
b.HasData(
new
{
Id = 1,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x400",
Name = "Royal Villa",
Occupancy = 4,
Price = 200.0,
Sqft = 550
},
new
{
Id = 2,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x401",
Name = "Premium Pool Villa",
Occupancy = 4,
Price = 300.0,
Sqft = 550
},
new
{
Id = 3,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x402",
Name = "Luxury Pool Villa",
Occupancy = 4,
Price = 400.0,
Sqft = 750
});
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.VillaNumber", b =>
{
b.Property<int>("Villa_Number")
.HasColumnType("int");
b.Property<string>("SpecialDetails")
.HasColumnType("nvarchar(max)");
b.Property<int>("VillaId")
.HasColumnType("int");
b.HasKey("Villa_Number");
b.HasIndex("VillaId");
b.ToTable("VillaNumbers");
b.HasData(
new
{
Villa_Number = 101,
VillaId = 1
},
new
{
Villa_Number = 102,
VillaId = 1
},
new
{
Villa_Number = 103,
VillaId = 1
},
new
{
Villa_Number = 104,
VillaId = 1
},
new
{
Villa_Number = 201,
VillaId = 2
},
new
{
Villa_Number = 202,
VillaId = 2
},
new
{
Villa_Number = 203,
VillaId = 2
},
new
{
Villa_Number = 301,
VillaId = 3
},
new
{
Villa_Number = 302,
VillaId = 3
});
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Amenity", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.Villa", "Villa")
.WithMany()
.HasForeignKey("VillaId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Villa");
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.VillaNumber", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.Villa", "Villa")
.WithMany()
.HasForeignKey("VillaId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Villa");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,67 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace WhiteLagoon.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class AddAmenityToDb : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Amenities",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Name = table.Column<string>(type: "nvarchar(max)", nullable: false),
Description = table.Column<string>(type: "nvarchar(max)", nullable: true),
VillaId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Amenities", x => x.Id);
table.ForeignKey(
name: "FK_Amenities_Villas_VillaId",
column: x => x.VillaId,
principalTable: "Villas",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.InsertData(
table: "Amenities",
columns: new[] { "Id", "Description", "Name", "VillaId" },
values: new object[,]
{
{ 1, null, "Private Pool", 1 },
{ 2, null, "Microwave", 1 },
{ 3, null, "Private Balcony", 1 },
{ 4, null, "1 king bed and 1 sofa bed", 1 },
{ 5, null, "Private Plunge Pool", 2 },
{ 6, null, "Microwave and Mini Refrigerator", 2 },
{ 7, null, "Private Balcony", 2 },
{ 8, null, "king bed or 2 double beds", 2 },
{ 9, null, "Private Pool", 3 },
{ 10, null, "Jacuzzi", 3 },
{ 11, null, "Private Balcony", 3 }
});
migrationBuilder.CreateIndex(
name: "IX_Amenities_VillaId",
table: "Amenities",
column: "VillaId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Amenities");
}
}
}
@@ -0,0 +1,535 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using WhiteLagoon.Infrastructure.Data;
#nullable disable
namespace WhiteLagoon.Infrastructure.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20230806135013_AddIdentityToDb")]
partial class AddIdentityToDb
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0-preview.6.23329.4")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<int>("AccessFailedCount")
.HasColumnType("int");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("bit");
b.Property<bool>("LockoutEnabled")
.HasColumnType("bit");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<string>("PhoneNumber")
.HasColumnType("nvarchar(max)");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("bit");
b.Property<string>("SecurityStamp")
.HasColumnType("nvarchar(max)");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("bit");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderKey")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("RoleId")
.HasColumnType("nvarchar(450)");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("Name")
.HasColumnType("nvarchar(450)");
b.Property<string>("Value")
.HasColumnType("nvarchar(max)");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Amenity", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("VillaId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("VillaId");
b.ToTable("Amenities");
b.HasData(
new
{
Id = 1,
Name = "Private Pool",
VillaId = 1
},
new
{
Id = 2,
Name = "Microwave",
VillaId = 1
},
new
{
Id = 3,
Name = "Private Balcony",
VillaId = 1
},
new
{
Id = 4,
Name = "1 king bed and 1 sofa bed",
VillaId = 1
},
new
{
Id = 5,
Name = "Private Plunge Pool",
VillaId = 2
},
new
{
Id = 6,
Name = "Microwave and Mini Refrigerator",
VillaId = 2
},
new
{
Id = 7,
Name = "Private Balcony",
VillaId = 2
},
new
{
Id = 8,
Name = "king bed or 2 double beds",
VillaId = 2
},
new
{
Id = 9,
Name = "Private Pool",
VillaId = 3
},
new
{
Id = 10,
Name = "Jacuzzi",
VillaId = 3
},
new
{
Id = 11,
Name = "Private Balcony",
VillaId = 3
});
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Villa", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime?>("Created_Date")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("ImageUrl")
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<int>("Occupancy")
.HasColumnType("int");
b.Property<double>("Price")
.HasColumnType("float");
b.Property<int>("Sqft")
.HasColumnType("int");
b.Property<DateTime?>("Updated_Date")
.HasColumnType("datetime2");
b.HasKey("Id");
b.ToTable("Villas");
b.HasData(
new
{
Id = 1,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x400",
Name = "Royal Villa",
Occupancy = 4,
Price = 200.0,
Sqft = 550
},
new
{
Id = 2,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x401",
Name = "Premium Pool Villa",
Occupancy = 4,
Price = 300.0,
Sqft = 550
},
new
{
Id = 3,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x402",
Name = "Luxury Pool Villa",
Occupancy = 4,
Price = 400.0,
Sqft = 750
});
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.VillaNumber", b =>
{
b.Property<int>("Villa_Number")
.HasColumnType("int");
b.Property<string>("SpecialDetails")
.HasColumnType("nvarchar(max)");
b.Property<int>("VillaId")
.HasColumnType("int");
b.HasKey("Villa_Number");
b.HasIndex("VillaId");
b.ToTable("VillaNumbers");
b.HasData(
new
{
Villa_Number = 101,
VillaId = 1
},
new
{
Villa_Number = 102,
VillaId = 1
},
new
{
Villa_Number = 103,
VillaId = 1
},
new
{
Villa_Number = 104,
VillaId = 1
},
new
{
Villa_Number = 201,
VillaId = 2
},
new
{
Villa_Number = 202,
VillaId = 2
},
new
{
Villa_Number = 203,
VillaId = 2
},
new
{
Villa_Number = 301,
VillaId = 3
},
new
{
Villa_Number = 302,
VillaId = 3
});
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Amenity", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.Villa", "Villa")
.WithMany("VillaAmenity")
.HasForeignKey("VillaId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Villa");
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.VillaNumber", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.Villa", "Villa")
.WithMany()
.HasForeignKey("VillaId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Villa");
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Villa", b =>
{
b.Navigation("VillaAmenity");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,224 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace WhiteLagoon.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class AddIdentityToDb : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AspNetRoles",
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
Name = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetUsers",
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
UserName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
NormalizedUserName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
Email = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
NormalizedEmail = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
EmailConfirmed = table.Column<bool>(type: "bit", nullable: false),
PasswordHash = table.Column<string>(type: "nvarchar(max)", nullable: true),
SecurityStamp = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(max)", nullable: true),
PhoneNumber = table.Column<string>(type: "nvarchar(max)", nullable: true),
PhoneNumberConfirmed = table.Column<bool>(type: "bit", nullable: false),
TwoFactorEnabled = table.Column<bool>(type: "bit", nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
LockoutEnabled = table.Column<bool>(type: "bit", nullable: false),
AccessFailedCount = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetRoleClaims",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
RoleId = table.Column<string>(type: "nvarchar(450)", nullable: false),
ClaimType = table.Column<string>(type: "nvarchar(max)", nullable: true),
ClaimValue = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserClaims",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false),
ClaimType = table.Column<string>(type: "nvarchar(max)", nullable: true),
ClaimValue = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserLogins",
columns: table => new
{
LoginProvider = table.Column<string>(type: "nvarchar(450)", nullable: false),
ProviderKey = table.Column<string>(type: "nvarchar(450)", nullable: false),
ProviderDisplayName = table.Column<string>(type: "nvarchar(max)", nullable: true),
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
table.ForeignKey(
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserRoles",
columns: table => new
{
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false),
RoleId = table.Column<string>(type: "nvarchar(450)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserTokens",
columns: table => new
{
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false),
LoginProvider = table.Column<string>(type: "nvarchar(450)", nullable: false),
Name = table.Column<string>(type: "nvarchar(450)", nullable: false),
Value = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
table.ForeignKey(
name: "FK_AspNetUserTokens_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_AspNetRoleClaims_RoleId",
table: "AspNetRoleClaims",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "RoleNameIndex",
table: "AspNetRoles",
column: "NormalizedName",
unique: true,
filter: "[NormalizedName] IS NOT NULL");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserClaims_UserId",
table: "AspNetUserClaims",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserLogins_UserId",
table: "AspNetUserLogins",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserRoles_RoleId",
table: "AspNetUserRoles",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "EmailIndex",
table: "AspNetUsers",
column: "NormalizedEmail");
migrationBuilder.CreateIndex(
name: "UserNameIndex",
table: "AspNetUsers",
column: "NormalizedUserName",
unique: true,
filter: "[NormalizedUserName] IS NOT NULL");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AspNetRoleClaims");
migrationBuilder.DropTable(
name: "AspNetUserClaims");
migrationBuilder.DropTable(
name: "AspNetUserLogins");
migrationBuilder.DropTable(
name: "AspNetUserRoles");
migrationBuilder.DropTable(
name: "AspNetUserTokens");
migrationBuilder.DropTable(
name: "AspNetRoles");
migrationBuilder.DropTable(
name: "AspNetUsers");
}
}
}
@@ -0,0 +1,542 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using WhiteLagoon.Infrastructure.Data;
#nullable disable
namespace WhiteLagoon.Infrastructure.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20230806135826_AddPropertiesToUsersTable")]
partial class AddPropertiesToUsersTable
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0-preview.6.23329.4")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderKey")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("RoleId")
.HasColumnType("nvarchar(450)");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("Name")
.HasColumnType("nvarchar(450)");
b.Property<string>("Value")
.HasColumnType("nvarchar(max)");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Amenity", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("VillaId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("VillaId");
b.ToTable("Amenities");
b.HasData(
new
{
Id = 1,
Name = "Private Pool",
VillaId = 1
},
new
{
Id = 2,
Name = "Microwave",
VillaId = 1
},
new
{
Id = 3,
Name = "Private Balcony",
VillaId = 1
},
new
{
Id = 4,
Name = "1 king bed and 1 sofa bed",
VillaId = 1
},
new
{
Id = 5,
Name = "Private Plunge Pool",
VillaId = 2
},
new
{
Id = 6,
Name = "Microwave and Mini Refrigerator",
VillaId = 2
},
new
{
Id = 7,
Name = "Private Balcony",
VillaId = 2
},
new
{
Id = 8,
Name = "king bed or 2 double beds",
VillaId = 2
},
new
{
Id = 9,
Name = "Private Pool",
VillaId = 3
},
new
{
Id = 10,
Name = "Jacuzzi",
VillaId = 3
},
new
{
Id = 11,
Name = "Private Balcony",
VillaId = 3
});
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.ApplicationUser", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<int>("AccessFailedCount")
.HasColumnType("int");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime2");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("bit");
b.Property<bool>("LockoutEnabled")
.HasColumnType("bit");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<string>("PhoneNumber")
.HasColumnType("nvarchar(max)");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("bit");
b.Property<string>("SecurityStamp")
.HasColumnType("nvarchar(max)");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("bit");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Villa", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime?>("Created_Date")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("ImageUrl")
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<int>("Occupancy")
.HasColumnType("int");
b.Property<double>("Price")
.HasColumnType("float");
b.Property<int>("Sqft")
.HasColumnType("int");
b.Property<DateTime?>("Updated_Date")
.HasColumnType("datetime2");
b.HasKey("Id");
b.ToTable("Villas");
b.HasData(
new
{
Id = 1,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x400",
Name = "Royal Villa",
Occupancy = 4,
Price = 200.0,
Sqft = 550
},
new
{
Id = 2,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x401",
Name = "Premium Pool Villa",
Occupancy = 4,
Price = 300.0,
Sqft = 550
},
new
{
Id = 3,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x402",
Name = "Luxury Pool Villa",
Occupancy = 4,
Price = 400.0,
Sqft = 750
});
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.VillaNumber", b =>
{
b.Property<int>("Villa_Number")
.HasColumnType("int");
b.Property<string>("SpecialDetails")
.HasColumnType("nvarchar(max)");
b.Property<int>("VillaId")
.HasColumnType("int");
b.HasKey("Villa_Number");
b.HasIndex("VillaId");
b.ToTable("VillaNumbers");
b.HasData(
new
{
Villa_Number = 101,
VillaId = 1
},
new
{
Villa_Number = 102,
VillaId = 1
},
new
{
Villa_Number = 103,
VillaId = 1
},
new
{
Villa_Number = 104,
VillaId = 1
},
new
{
Villa_Number = 201,
VillaId = 2
},
new
{
Villa_Number = 202,
VillaId = 2
},
new
{
Villa_Number = 203,
VillaId = 2
},
new
{
Villa_Number = 301,
VillaId = 3
},
new
{
Villa_Number = 302,
VillaId = 3
});
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("WhiteLagoon.Domain.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Amenity", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.Villa", "Villa")
.WithMany("VillaAmenity")
.HasForeignKey("VillaId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Villa");
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.VillaNumber", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.Villa", "Villa")
.WithMany()
.HasForeignKey("VillaId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Villa");
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Villa", b =>
{
b.Navigation("VillaAmenity");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,41 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace WhiteLagoon.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class AddPropertiesToUsersTable : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "CreatedAt",
table: "AspNetUsers",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
migrationBuilder.AddColumn<string>(
name: "Name",
table: "AspNetUsers",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "CreatedAt",
table: "AspNetUsers");
migrationBuilder.DropColumn(
name: "Name",
table: "AspNetUsers");
}
}
}
@@ -0,0 +1,635 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using WhiteLagoon.Infrastructure.Data;
#nullable disable
namespace WhiteLagoon.Infrastructure.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20230807153245_addBookingToDb")]
partial class addBookingToDb
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0-preview.6.23329.4")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderKey")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("RoleId")
.HasColumnType("nvarchar(450)");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("Name")
.HasColumnType("nvarchar(450)");
b.Property<string>("Value")
.HasColumnType("nvarchar(max)");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Amenity", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("VillaId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("VillaId");
b.ToTable("Amenities");
b.HasData(
new
{
Id = 1,
Name = "Private Pool",
VillaId = 1
},
new
{
Id = 2,
Name = "Microwave",
VillaId = 1
},
new
{
Id = 3,
Name = "Private Balcony",
VillaId = 1
},
new
{
Id = 4,
Name = "1 king bed and 1 sofa bed",
VillaId = 1
},
new
{
Id = 5,
Name = "Private Plunge Pool",
VillaId = 2
},
new
{
Id = 6,
Name = "Microwave and Mini Refrigerator",
VillaId = 2
},
new
{
Id = 7,
Name = "Private Balcony",
VillaId = 2
},
new
{
Id = 8,
Name = "king bed or 2 double beds",
VillaId = 2
},
new
{
Id = 9,
Name = "Private Pool",
VillaId = 3
},
new
{
Id = 10,
Name = "Jacuzzi",
VillaId = 3
},
new
{
Id = 11,
Name = "Private Balcony",
VillaId = 3
});
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.ApplicationUser", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<int>("AccessFailedCount")
.HasColumnType("int");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime2");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("bit");
b.Property<bool>("LockoutEnabled")
.HasColumnType("bit");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<string>("PhoneNumber")
.HasColumnType("nvarchar(max)");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("bit");
b.Property<string>("SecurityStamp")
.HasColumnType("nvarchar(max)");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("bit");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Booking", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("ActualCheckInDate")
.HasColumnType("datetime2");
b.Property<DateTime>("ActualCheckOutDate")
.HasColumnType("datetime2");
b.Property<DateTime>("BookingDate")
.HasColumnType("datetime2");
b.Property<DateOnly>("CheckInDate")
.HasColumnType("date");
b.Property<DateOnly>("CheckOutDate")
.HasColumnType("date");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsPaymentSuccessful")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("Nights")
.HasColumnType("int");
b.Property<DateTime>("PaymentDate")
.HasColumnType("datetime2");
b.Property<string>("Phone")
.HasColumnType("nvarchar(max)");
b.Property<string>("Status")
.HasColumnType("nvarchar(max)");
b.Property<string>("StripePaymentIntentId")
.HasColumnType("nvarchar(max)");
b.Property<string>("StripeSessionId")
.HasColumnType("nvarchar(max)");
b.Property<double>("TotalCost")
.HasColumnType("float");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.Property<int>("VillaId")
.HasColumnType("int");
b.Property<int>("VillaNumber")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.HasIndex("VillaId");
b.ToTable("Bookings");
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Villa", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime?>("Created_Date")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("ImageUrl")
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<int>("Occupancy")
.HasColumnType("int");
b.Property<double>("Price")
.HasColumnType("float");
b.Property<int>("Sqft")
.HasColumnType("int");
b.Property<DateTime?>("Updated_Date")
.HasColumnType("datetime2");
b.HasKey("Id");
b.ToTable("Villas");
b.HasData(
new
{
Id = 1,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x400",
Name = "Royal Villa",
Occupancy = 4,
Price = 200.0,
Sqft = 550
},
new
{
Id = 2,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x401",
Name = "Premium Pool Villa",
Occupancy = 4,
Price = 300.0,
Sqft = 550
},
new
{
Id = 3,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x402",
Name = "Luxury Pool Villa",
Occupancy = 4,
Price = 400.0,
Sqft = 750
});
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.VillaNumber", b =>
{
b.Property<int>("Villa_Number")
.HasColumnType("int");
b.Property<string>("SpecialDetails")
.HasColumnType("nvarchar(max)");
b.Property<int>("VillaId")
.HasColumnType("int");
b.HasKey("Villa_Number");
b.HasIndex("VillaId");
b.ToTable("VillaNumbers");
b.HasData(
new
{
Villa_Number = 101,
VillaId = 1
},
new
{
Villa_Number = 102,
VillaId = 1
},
new
{
Villa_Number = 103,
VillaId = 1
},
new
{
Villa_Number = 104,
VillaId = 1
},
new
{
Villa_Number = 201,
VillaId = 2
},
new
{
Villa_Number = 202,
VillaId = 2
},
new
{
Villa_Number = 203,
VillaId = 2
},
new
{
Villa_Number = 301,
VillaId = 3
},
new
{
Villa_Number = 302,
VillaId = 3
});
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("WhiteLagoon.Domain.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Amenity", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.Villa", "Villa")
.WithMany("VillaAmenity")
.HasForeignKey("VillaId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Villa");
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Booking", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.ApplicationUser", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("WhiteLagoon.Domain.Entities.Villa", "Villa")
.WithMany()
.HasForeignKey("VillaId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
b.Navigation("Villa");
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.VillaNumber", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.Villa", "Villa")
.WithMany()
.HasForeignKey("VillaId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Villa");
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Villa", b =>
{
b.Navigation("VillaAmenity");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,74 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace WhiteLagoon.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class addBookingToDb : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Bookings",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false),
VillaId = table.Column<int>(type: "int", nullable: false),
Name = table.Column<string>(type: "nvarchar(max)", nullable: false),
Email = table.Column<string>(type: "nvarchar(max)", nullable: false),
Phone = table.Column<string>(type: "nvarchar(max)", nullable: true),
TotalCost = table.Column<double>(type: "float", nullable: false),
Nights = table.Column<int>(type: "int", nullable: false),
Status = table.Column<string>(type: "nvarchar(max)", nullable: true),
BookingDate = table.Column<DateTime>(type: "datetime2", nullable: false),
CheckInDate = table.Column<DateOnly>(type: "date", nullable: false),
CheckOutDate = table.Column<DateOnly>(type: "date", nullable: false),
IsPaymentSuccessful = table.Column<bool>(type: "bit", nullable: false),
PaymentDate = table.Column<DateTime>(type: "datetime2", nullable: false),
StripeSessionId = table.Column<string>(type: "nvarchar(max)", nullable: true),
StripePaymentIntentId = table.Column<string>(type: "nvarchar(max)", nullable: true),
ActualCheckInDate = table.Column<DateTime>(type: "datetime2", nullable: false),
ActualCheckOutDate = table.Column<DateTime>(type: "datetime2", nullable: false),
VillaNumber = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Bookings", x => x.Id);
table.ForeignKey(
name: "FK_Bookings_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Bookings_Villas_VillaId",
column: x => x.VillaId,
principalTable: "Villas",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Bookings_UserId",
table: "Bookings",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_Bookings_VillaId",
table: "Bookings",
column: "VillaId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Bookings");
}
}
}
@@ -0,0 +1,632 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using WhiteLagoon.Infrastructure.Data;
#nullable disable
namespace WhiteLagoon.Infrastructure.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
partial class ApplicationDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0-preview.6.23329.4")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderKey")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("RoleId")
.HasColumnType("nvarchar(450)");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("Name")
.HasColumnType("nvarchar(450)");
b.Property<string>("Value")
.HasColumnType("nvarchar(max)");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Amenity", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("VillaId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("VillaId");
b.ToTable("Amenities");
b.HasData(
new
{
Id = 1,
Name = "Private Pool",
VillaId = 1
},
new
{
Id = 2,
Name = "Microwave",
VillaId = 1
},
new
{
Id = 3,
Name = "Private Balcony",
VillaId = 1
},
new
{
Id = 4,
Name = "1 king bed and 1 sofa bed",
VillaId = 1
},
new
{
Id = 5,
Name = "Private Plunge Pool",
VillaId = 2
},
new
{
Id = 6,
Name = "Microwave and Mini Refrigerator",
VillaId = 2
},
new
{
Id = 7,
Name = "Private Balcony",
VillaId = 2
},
new
{
Id = 8,
Name = "king bed or 2 double beds",
VillaId = 2
},
new
{
Id = 9,
Name = "Private Pool",
VillaId = 3
},
new
{
Id = 10,
Name = "Jacuzzi",
VillaId = 3
},
new
{
Id = 11,
Name = "Private Balcony",
VillaId = 3
});
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.ApplicationUser", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<int>("AccessFailedCount")
.HasColumnType("int");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime2");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("bit");
b.Property<bool>("LockoutEnabled")
.HasColumnType("bit");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<string>("PhoneNumber")
.HasColumnType("nvarchar(max)");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("bit");
b.Property<string>("SecurityStamp")
.HasColumnType("nvarchar(max)");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("bit");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Booking", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("ActualCheckInDate")
.HasColumnType("datetime2");
b.Property<DateTime>("ActualCheckOutDate")
.HasColumnType("datetime2");
b.Property<DateTime>("BookingDate")
.HasColumnType("datetime2");
b.Property<DateOnly>("CheckInDate")
.HasColumnType("date");
b.Property<DateOnly>("CheckOutDate")
.HasColumnType("date");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsPaymentSuccessful")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("Nights")
.HasColumnType("int");
b.Property<DateTime>("PaymentDate")
.HasColumnType("datetime2");
b.Property<string>("Phone")
.HasColumnType("nvarchar(max)");
b.Property<string>("Status")
.HasColumnType("nvarchar(max)");
b.Property<string>("StripePaymentIntentId")
.HasColumnType("nvarchar(max)");
b.Property<string>("StripeSessionId")
.HasColumnType("nvarchar(max)");
b.Property<double>("TotalCost")
.HasColumnType("float");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.Property<int>("VillaId")
.HasColumnType("int");
b.Property<int>("VillaNumber")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.HasIndex("VillaId");
b.ToTable("Bookings");
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Villa", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime?>("Created_Date")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("ImageUrl")
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<int>("Occupancy")
.HasColumnType("int");
b.Property<double>("Price")
.HasColumnType("float");
b.Property<int>("Sqft")
.HasColumnType("int");
b.Property<DateTime?>("Updated_Date")
.HasColumnType("datetime2");
b.HasKey("Id");
b.ToTable("Villas");
b.HasData(
new
{
Id = 1,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x400",
Name = "Royal Villa",
Occupancy = 4,
Price = 200.0,
Sqft = 550
},
new
{
Id = 2,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x401",
Name = "Premium Pool Villa",
Occupancy = 4,
Price = 300.0,
Sqft = 550
},
new
{
Id = 3,
Description = "Fusce 11 tincidunt maximus leo, sed scelerisque massa auctor sit amet. Donec ex mauris, hendrerit quis nibh ac, efficitur fringilla enim.",
ImageUrl = "https://placehold.co/600x402",
Name = "Luxury Pool Villa",
Occupancy = 4,
Price = 400.0,
Sqft = 750
});
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.VillaNumber", b =>
{
b.Property<int>("Villa_Number")
.HasColumnType("int");
b.Property<string>("SpecialDetails")
.HasColumnType("nvarchar(max)");
b.Property<int>("VillaId")
.HasColumnType("int");
b.HasKey("Villa_Number");
b.HasIndex("VillaId");
b.ToTable("VillaNumbers");
b.HasData(
new
{
Villa_Number = 101,
VillaId = 1
},
new
{
Villa_Number = 102,
VillaId = 1
},
new
{
Villa_Number = 103,
VillaId = 1
},
new
{
Villa_Number = 104,
VillaId = 1
},
new
{
Villa_Number = 201,
VillaId = 2
},
new
{
Villa_Number = 202,
VillaId = 2
},
new
{
Villa_Number = 203,
VillaId = 2
},
new
{
Villa_Number = 301,
VillaId = 3
},
new
{
Villa_Number = 302,
VillaId = 3
});
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("WhiteLagoon.Domain.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.ApplicationUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Amenity", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.Villa", "Villa")
.WithMany("VillaAmenity")
.HasForeignKey("VillaId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Villa");
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Booking", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.ApplicationUser", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("WhiteLagoon.Domain.Entities.Villa", "Villa")
.WithMany()
.HasForeignKey("VillaId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
b.Navigation("Villa");
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.VillaNumber", b =>
{
b.HasOne("WhiteLagoon.Domain.Entities.Villa", "Villa")
.WithMany()
.HasForeignKey("VillaId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Villa");
});
modelBuilder.Entity("WhiteLagoon.Domain.Entities.Villa", b =>
{
b.Navigation("VillaAmenity");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Application.Common.Interfaces;
using WhiteLagoon.Domain.Entities;
using WhiteLagoon.Infrastructure.Data;
namespace WhiteLagoon.Infrastructure.Repository
{
public class AmenityRepository : Repository<Amenity>, IAmenityRepository
{
private readonly ApplicationDbContext _db;
public AmenityRepository(ApplicationDbContext db) : base(db)
{
_db = db;
}
public void Update(Amenity entity)
{
_db.Amenities.Update(entity);
}
}
}
@@ -0,0 +1,24 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Application.Common.Interfaces;
using WhiteLagoon.Domain.Entities;
using WhiteLagoon.Infrastructure.Data;
namespace WhiteLagoon.Infrastructure.Repository
{
public class ApplicationUserRepository : Repository<ApplicationUser>, IApplicationUserRepository
{
private readonly ApplicationDbContext _db;
public ApplicationUserRepository(ApplicationDbContext db) : base(db)
{
_db = db;
}
}
}
@@ -0,0 +1,31 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Application.Common.Interfaces;
using WhiteLagoon.Application.Common.Utility;
using WhiteLagoon.Domain.Entities;
using WhiteLagoon.Infrastructure.Data;
namespace WhiteLagoon.Infrastructure.Repository
{
public class BookingRepository : Repository<Booking>, IBookingRepository
{
private readonly ApplicationDbContext _db;
public BookingRepository(ApplicationDbContext db) : base(db)
{
_db = db;
}
public void Update(Booking entity)
{
_db.Bookings.Update(entity);
}
}
}
@@ -0,0 +1,91 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Application.Common.Interfaces;
using WhiteLagoon.Domain.Entities;
using WhiteLagoon.Infrastructure.Data;
namespace WhiteLagoon.Infrastructure.Repository
{
public class Repository<T> : IRepository<T> where T : class
{
private readonly ApplicationDbContext _db;
internal DbSet<T> dbSet;
public Repository(ApplicationDbContext db)
{
_db = db;
dbSet = _db.Set<T>();
}
public void Add(T entity)
{
dbSet.Add(entity);
}
public bool Any(Expression<Func<T, bool>> filter)
{
return dbSet.Any(filter);
}
public T Get(Expression<Func<T, bool>> filter, string? includeProperties = null, bool tracked = false)
{
IQueryable<T> query;
if (tracked)
{
query = dbSet;
}
else
{
query=dbSet.AsNoTracking();
}
if (filter != null)
{
query = query.Where(filter);
}
if (!string.IsNullOrEmpty(includeProperties))
{
//Villa,VillaNumber -- case sensitive
foreach (var includeProp in includeProperties
.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProp.Trim());
}
}
return query.FirstOrDefault();
}
public IEnumerable<T> GetAll(Expression<Func<T, bool>>? filter = null, string? includeProperties = null, bool tracked = false)
{
IQueryable<T> query;
if (tracked)
{
query = dbSet;
}
else
{
query = dbSet.AsNoTracking();
}
if (filter != null)
{
query = query.Where(filter);
}
if (!string.IsNullOrEmpty(includeProperties))
{
foreach (var includeProp in includeProperties
.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProp.Trim());
}
}
return query.ToList();
}
public void Remove(T entity)
{
dbSet.Remove(entity);
}
}
}
@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Application.Common.Interfaces;
using WhiteLagoon.Infrastructure.Data;
namespace WhiteLagoon.Infrastructure.Repository
{
public class UnitOfWork : IUnitOfWork
{
private readonly ApplicationDbContext _db;
public IVillaRepository Villa {get; private set;}
public IApplicationUserRepository User { get; private set; }
public IAmenityRepository Amenity { get; private set; }
public IBookingRepository Booking { get; private set; }
public IVillaNumberRepository VillaNumber { get; private set;}
public UnitOfWork(ApplicationDbContext db)
{
_db = db;
Villa = new VillaRepository(_db);
User = new ApplicationUserRepository(_db);
Booking = new BookingRepository(_db);
Amenity = new AmenityRepository(_db);
VillaNumber = new VillaNumberRepository(_db);
}
public void Save()
{
_db.SaveChanges();
}
}
}
@@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Application.Common.Interfaces;
using WhiteLagoon.Domain.Entities;
using WhiteLagoon.Infrastructure.Data;
namespace WhiteLagoon.Infrastructure.Repository
{
public class VillaNumberRepository : Repository<VillaNumber>, IVillaNumberRepository
{
private readonly ApplicationDbContext _db;
public VillaNumberRepository(ApplicationDbContext db) : base(db)
{
_db = db;
}
public void Update(VillaNumber entity)
{
_db.VillaNumbers.Update(entity);
}
}
}
@@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WhiteLagoon.Application.Common.Interfaces;
using WhiteLagoon.Domain.Entities;
using WhiteLagoon.Infrastructure.Data;
namespace WhiteLagoon.Infrastructure.Repository
{
public class VillaRepository : Repository<Villa>, IVillaRepository
{
private readonly ApplicationDbContext _db;
public VillaRepository(ApplicationDbContext db) : base(db)
{
_db = db;
}
public void Update(Villa entity)
{
_db.Villas.Update(entity);
}
}
}
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.0-preview.6.23329.11" />
<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="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0-preview.6.23329.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="SendGrid" Version="9.28.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WhiteLagoon.Application\WhiteLagoon.Application.csproj" />
</ItemGroup>
</Project>
@@ -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();
}
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace WhiteLagoon.Web.Models
{
public class ErrorViewModel
{
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
}
}
+77
View File
@@ -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"
}
}
}
}
+13
View File
@@ -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; }
}
}
+12
View File
@@ -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; }
}
}
+18
View File
@@ -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; }
}
}
+33
View File
@@ -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> &nbsp; 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> &nbsp; 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> &nbsp; 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> &nbsp; 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>
}
+93
View File
@@ -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> &nbsp; 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>

Some files were not shown because too many files have changed in this diff Show More