diff --git a/ASI.Basecode.Data/Interfaces/IRoomManagementRepository.cs b/ASI.Basecode.Data/Interfaces/IRoomManagementRepository.cs new file mode 100644 index 0000000..4e1fe99 --- /dev/null +++ b/ASI.Basecode.Data/Interfaces/IRoomManagementRepository.cs @@ -0,0 +1,17 @@ +using ASI.Basecode.Data.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ASI.Basecode.Data.Interfaces +{ + public interface IRoomManagementRepository + { + IEnumerable RetrieveAll(); + void Add(RoomManagement model); + void Update(RoomManagement model); + void Delete(int RoomId); + } +} diff --git a/ASI.Basecode.Data/Models/RoomManagement.cs b/ASI.Basecode.Data/Models/RoomManagement.cs new file mode 100644 index 0000000..8f6d270 --- /dev/null +++ b/ASI.Basecode.Data/Models/RoomManagement.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ASI.Basecode.Data.Models +{ + public class RoomManagement + { + public int RoomId { get; set; } + + public string RoomType { get; set; } + + public string RoomCode { get; set; } + + public string RoomName { get; set; } + + public int RoomCapacity { get; set; } + + public string HasEquipments { get; set; } + + public string RoomLocation { get; set; } + + public string Description { get; set; } // e.g., uses of the room + } +} diff --git a/ASI.Basecode.Data/Repositories/RoomManagementRepository.cs b/ASI.Basecode.Data/Repositories/RoomManagementRepository.cs new file mode 100644 index 0000000..8ea00e8 --- /dev/null +++ b/ASI.Basecode.Data/Repositories/RoomManagementRepository.cs @@ -0,0 +1,49 @@ +using ASI.Basecode.Data.Interfaces; +using ASI.Basecode.Data.Models; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ASI.Basecode.Data.Repositories +{ + public class RoomManagementRepository: IRoomManagementRepository + { + private readonly List _datasaroom = new List(); + private int _nextroomId = 1; + + public IEnumerable RetrieveAll() + { + + return _datasaroom; + } + + public void Add(RoomManagement model) + { + model.RoomId = _nextroomId++; + _datasaroom.Add(model); + } + + public void Update(RoomManagement model) + { + var existingData = _datasaroom.Where(x => x.RoomId == model.RoomId).FirstOrDefault(); + if (existingData != null) + { + existingData = model; + } + } + + public void Delete(int RoomId) + { + var existingData = _datasaroom.Where(x => x.RoomId == RoomId).FirstOrDefault(); + /*if (existingData != null) + { + _datasaroom.Remove(existingData); + }*/ + + _datasaroom.Remove(existingData); + } + } +} diff --git a/ASI.Basecode.Services/Interfaces/IRoomManagementService.cs b/ASI.Basecode.Services/Interfaces/IRoomManagementService.cs new file mode 100644 index 0000000..4dc6fef --- /dev/null +++ b/ASI.Basecode.Services/Interfaces/IRoomManagementService.cs @@ -0,0 +1,18 @@ +using ASI.Basecode.Data.Models; +using ASI.Basecode.Services.ServiceModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ASI.Basecode.Services.Interfaces +{ + public interface IRoomManagementService + { + IEnumerable RetrieveAll(); + void Add(RoomManagementViewModel model); + void Update(RoomManagementViewModel model); + void Delete(int RoomId); + } +} diff --git a/ASI.Basecode.Services/ServiceModels/RoomManagementViewModel.cs b/ASI.Basecode.Services/ServiceModels/RoomManagementViewModel.cs new file mode 100644 index 0000000..f722ce9 --- /dev/null +++ b/ASI.Basecode.Services/ServiceModels/RoomManagementViewModel.cs @@ -0,0 +1,36 @@ +using ASI.Basecode.Data.Models; +using ASI.Basecode.Services.ServiceModels; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ASI.Basecode.Services.ServiceModels +{ + public class RoomManagementViewModel + { + [Key] + public int RoomId { get; set; } + + [Required] + public string RoomType { get; set; } + + [Required] + public string RoomCode { get; set; } + + [Required] + public string RoomName { get; set; } + + [Required] + public int RoomCapacity { get; set; } + + public string HasEquipments { get; set; } + + [Required] + public string RoomLocation { get; set; } + + public string Description { get; set; } // e.g., uses of the room + } +} diff --git a/ASI.Basecode.Services/Services/RoomManagementService.cs b/ASI.Basecode.Services/Services/RoomManagementService.cs new file mode 100644 index 0000000..cba083a --- /dev/null +++ b/ASI.Basecode.Services/Services/RoomManagementService.cs @@ -0,0 +1,67 @@ +using ASI.Basecode.Data.Interfaces; +using ASI.Basecode.Data.Repositories; +using ASI.Basecode.Services.ServiceModels; +using ASI.Basecode.Services.Interfaces; +using AutoMapper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ASI.Basecode.Data.Models; + +namespace ASI.Basecode.Services.Services +{ + public class RoomManagementService : IRoomManagementService + { + private readonly List _room = new List(); + private readonly IRoomManagementRepository _roomRepository; + private readonly IMapper _mapper; + + public RoomManagementService(IRoomManagementRepository RoomManagementRepository, IMapper mapper) + { + _roomRepository = RoomManagementRepository; + _mapper = mapper; + _room.Add(new RoomManagementViewModel { RoomId = 1, RoomName = "Room A", RoomCode = "Room A", RoomType = "Room A", RoomLocation = "First Floor", RoomCapacity = 1 , HasEquipments = "Room A" }); + + } + + public IEnumerable RetrieveAll() + { + + var data = _roomRepository.RetrieveAll().Select(s => new RoomManagementViewModel + { + RoomId = s.RoomId, + RoomName = s.RoomName, + RoomCode = s.RoomCode, + RoomType = s.RoomType, + RoomLocation = s.RoomLocation, + RoomCapacity = s.RoomCapacity, + HasEquipments = s.HasEquipments, + }); + return data; + } + + + public void Add(RoomManagementViewModel model) + { + var newModel = new RoomManagement(); + _mapper.Map(model, newModel); + + _roomRepository.Add(newModel); + } + + + public void Update(RoomManagementViewModel model) + { + var existingData = _roomRepository.RetrieveAll().Where(s => s.RoomId == model.RoomId).FirstOrDefault(); + _mapper.Map(model, existingData); + _roomRepository.Update(existingData); + } + + public void Delete(int RoomId) + { + _roomRepository.Delete(RoomId); + } + } +} diff --git a/ASI.Basecode.WebApp/ASI.Basecode.WebApp.csproj b/ASI.Basecode.WebApp/ASI.Basecode.WebApp.csproj index ee031fa..4f21f09 100644 --- a/ASI.Basecode.WebApp/ASI.Basecode.WebApp.csproj +++ b/ASI.Basecode.WebApp/ASI.Basecode.WebApp.csproj @@ -6,6 +6,40 @@ 872bac6a-ed64-4226-a559-064bd37b166e + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -39,4 +73,12 @@ + + + + + + + <_ContentIncludedByDefault Remove="Views\Shared\Calendar.cshtml" /> + diff --git a/ASI.Basecode.WebApp/Controllers/AccountController.cs b/ASI.Basecode.WebApp/Controllers/AccountController.cs index 3a55a55..d2f3f36 100644 --- a/ASI.Basecode.WebApp/Controllers/AccountController.cs +++ b/ASI.Basecode.WebApp/Controllers/AccountController.cs @@ -26,6 +26,7 @@ public class AccountController : ControllerBase private readonly TokenProviderOptionsFactory _tokenProviderOptionsFactory; private readonly IConfiguration _appConfiguration; private readonly IUserService _userService; + private const string AdminUserId = "admin"; // Temporary admin user ID /// /// Initializes a new instance of the class. @@ -77,7 +78,7 @@ public ActionResult Login() /// The model. /// The return URL. /// Created response view - [HttpPost] + /*[HttpPost] [AllowAnonymous] public async Task Login(LoginViewModel model, string returnUrl) { @@ -92,7 +93,7 @@ public async Task Login(LoginViewModel model, string returnUrl) return RedirectToAction("Index", "Home"); - /*var loginResult = _userService.AuthenticateUser(model.UserId, model.Password, ref user); + *//*var loginResult = _userService.AuthenticateUser(model.UserId, model.Password, ref user); if (loginResult == LoginResult.Success) { // 認証OK @@ -106,7 +107,40 @@ public async Task Login(LoginViewModel model, string returnUrl) TempData["ErrorMessage"] = "Incorrect UserId or Password"; return View(); } - return View();*/ + return View();*//* + }*/ + + //the code above being commented is the original login logic of basecode. The code below this comment is the temporary solution for login para mapasok si admin + + [HttpPost] + [AllowAnonymous] + public async Task Login(LoginViewModel model, string returnUrl) + { + this._session.SetString("HasSession", "Exist"); + + // Temporary login logic + if (model.UserId == AdminUserId && model.Password == "adminpass") + { + // Admin login + User user = new() { Id = 1, UserId = AdminUserId, Name = "Admin User", Password = "adminpass" }; + await this._signInManager.SignInAsync(user); + this._session.SetString("UserName", user.Name); + this._session.SetString("UserRole", "Admin"); + return RedirectToAction("Index", "Admin"); + } + else if (!string.IsNullOrEmpty(model.UserId) && !string.IsNullOrEmpty(model.Password)) + { + // Regular user login + User user = new() { Id = 2, UserId = model.UserId, Name = model.UserId, Password = model.Password }; + await this._signInManager.SignInAsync(user); + this._session.SetString("UserName", user.Name); + this._session.SetString("UserRole", "User"); + return RedirectToAction("Index", "Home"); + } + + // Invalid login + TempData["ErrorMessage"] = "Incorrect UserId or Password"; + return View(); } [HttpGet] @@ -146,5 +180,17 @@ public async Task SignOutUser() await this._signInManager.SignOutAsync(); return RedirectToAction("Login", "Account"); } + + /// + /// Sign Out current admin and return login view. + /// + /// Created response view + [AllowAnonymous] + public async Task SignOutAdmin() + { + await this._signInManager.SignOutAsync(); + HttpContext.Session.Clear(); + return RedirectToAction("Login", "Account"); + } } } diff --git a/ASI.Basecode.WebApp/Controllers/AdminController.cs b/ASI.Basecode.WebApp/Controllers/AdminController.cs new file mode 100644 index 0000000..549089f --- /dev/null +++ b/ASI.Basecode.WebApp/Controllers/AdminController.cs @@ -0,0 +1,188 @@ +using ASI.Basecode.Data.Interfaces; +using ASI.Basecode.Services.Interfaces; +using ASI.Basecode.Services.ServiceModels; +using ASI.Basecode.Data.Models; +using ASI.Basecode.Services.Services; +using ASI.Basecode.WebApp.Mvc; +using AutoMapper; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using System; +using System.Linq; + +namespace ASI.Basecode.WebApp.Controllers +{ + /// + /// Admin Controller + /// + public class AdminController : ControllerBase + { + + private readonly IRoomManagementService _roomService; + /// + /// Constructor + /// + /// + /// + /// + /// + /// + public AdminController(IRoomManagementService roomService, + IHttpContextAccessor httpContextAccessor, + ILoggerFactory loggerFactory, + IConfiguration configuration, + IMapper mapper = null) : base(httpContextAccessor, loggerFactory, configuration, mapper) + { + _roomService = roomService; + } + + /// + /// Returns Admin Home View. + /// + /// Admin Home View + public IActionResult Index() + { + if (HttpContext.Session.GetString("UserRole") != "Admin") + { + return RedirectToAction("Login", "Account"); + } + return View(); + } + + + /// + /// Returns Admin Analytics View. + /// + /// Admin Analytics View + public IActionResult Analytics() + { + if (HttpContext.Session.GetString("UserRole") != "Admin") + { + return RedirectToAction("Login", "Account"); + } + return View(); + } + + /// + /// Returns Manage Roles View. + /// + /// Manage Roles View + public IActionResult ManageRoles() + { + if (HttpContext.Session.GetString("UserRole") != "Admin") + { + return RedirectToAction("Login", "Account"); + } + return View(); + } + + /// + /// Returns Admin Settings View. + /// + /// Admin Settings View + public IActionResult AdminSettings() + { + if (HttpContext.Session.GetString("UserRole") != "Admin") + { + return RedirectToAction("AdminSettings", "Admin"); + } + return View(); + } + + + + //ROOM MANAGEMENT + public IActionResult RoomManagement() + { + var datasaroom = _roomService.RetrieveAll(); + return View(datasaroom); + } + + #region[HttpGet] + [HttpGet] + public IActionResult Details(int RoomId) + { + var roommanagement = _roomService.RetrieveAll().FirstOrDefault(x => x.RoomId == RoomId); + if (roommanagement == null) + { + return NotFound(); + } + return View(roommanagement); + } + + [HttpGet] + public IActionResult CreateRoom() + { + return View(); + } + + [HttpGet] + public IActionResult Edit(int RoomId) + { + var roommanagement = _roomService.RetrieveAll().FirstOrDefault(x => x.RoomId == RoomId); + if (roommanagement == null) + { + return NotFound(); + } + return View(roommanagement); + } + + [HttpGet] + public IActionResult Delete(int RoomId) + { + var roommanagement = _roomService.RetrieveAll().FirstOrDefault(x => x.RoomId == RoomId); + if (roommanagement == null) + { + return NotFound(); + } + return View(roommanagement); + } + #endregion + + #region [HttpPost] + [HttpPost] + public IActionResult PostCreate(RoomManagementViewModel model) + { + bool isDuplicate = _roomService.RetrieveAll().Any(data => data.RoomCode == model.RoomCode || data.RoomName == model.RoomName); + if (isDuplicate) + { + TempData["DuplicateErr"] = "Room Already Exists"; + return RedirectToAction("CreateRoom", model); + } + + + _roomService.Add(model); + TempData["SuccessMessage"] = "Added Successfuly!"; + return RedirectToAction("RoomManagement"); + + } + [HttpPost] + public IActionResult PostUpdate(RoomManagementViewModel model) + { + _roomService.Update(model); + return RedirectToAction("RoomManagement"); + } + + [HttpPost] + public IActionResult PostDelete(int RoomId) + { + + try + { + _roomService.Delete(RoomId); + TempData["SuccessMessage"] = "Room Deleted Successfully!"; + } + catch (Exception ex) + { + TempData["ErrorMessage"] = $"Error deleting room: {ex.Message}"; + } + + return RedirectToAction("RoomManagement"); + } + + #endregion + + } +} diff --git a/ASI.Basecode.WebApp/Controllers/HomeController.cs b/ASI.Basecode.WebApp/Controllers/HomeController.cs index b0c6e99..19d579a 100644 --- a/ASI.Basecode.WebApp/Controllers/HomeController.cs +++ b/ASI.Basecode.WebApp/Controllers/HomeController.cs @@ -1,40 +1,52 @@ -using ASI.Basecode.WebApp.Mvc; -using AutoMapper; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; + using ASI.Basecode.WebApp.Mvc; + using AutoMapper; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.Extensions.Configuration; + using Microsoft.Extensions.Logging; -namespace ASI.Basecode.WebApp.Controllers -{ - /// - /// Home Controller - /// - public class HomeController : ControllerBase + namespace ASI.Basecode.WebApp.Controllers { /// - /// Constructor + /// Home Controller /// - /// - /// - /// - /// - /// - public HomeController(IHttpContextAccessor httpContextAccessor, - ILoggerFactory loggerFactory, - IConfiguration configuration, - IMapper mapper = null) : base(httpContextAccessor, loggerFactory, configuration, mapper) + public class HomeController : ControllerBase { + /// + /// Constructor + /// + /// + /// + /// + /// + /// + public HomeController(IHttpContextAccessor httpContextAccessor, + ILoggerFactory loggerFactory, + IConfiguration configuration, + IMapper mapper = null) : base(httpContextAccessor, loggerFactory, configuration, mapper) + { - } + } - /// - /// Returns Home View. - /// - /// Home View - public IActionResult Index() - { - return View(); - } + /// + /// Returns Home View. + /// + /// Home View + public IActionResult Index() + { + return View(); + } + public IActionResult ViewBookings() + { + return View(); + } + public IActionResult Calendar() + { + return View(); + } + public IActionResult UserSettings() + { + return View(); + } + } } -} diff --git a/ASI.Basecode.WebApp/Program.cs b/ASI.Basecode.WebApp/Program.cs index c31c03e..3277f46 100644 --- a/ASI.Basecode.WebApp/Program.cs +++ b/ASI.Basecode.WebApp/Program.cs @@ -36,5 +36,19 @@ app.MapControllers(); app.MapRazorPages(); + +app.UseEndpoints(endpoints => +{ + endpoints.MapControllerRoute( + name: "admin", + pattern: "Admin/{action=Index}/{id?}", + defaults: new { controller = "Admin" }); + + endpoints.MapControllerRoute( + name: "default", + pattern: "{controller=Home}/{action=Index}/{id?}"); +}); + + // Run application app.Run(); diff --git a/ASI.Basecode.WebApp/Startup.AutoMapper.cs b/ASI.Basecode.WebApp/Startup.AutoMapper.cs index fee2d42..8267c77 100644 --- a/ASI.Basecode.WebApp/Startup.AutoMapper.cs +++ b/ASI.Basecode.WebApp/Startup.AutoMapper.cs @@ -26,6 +26,7 @@ private class AutoMapperProfileConfiguration : Profile public AutoMapperProfileConfiguration() { CreateMap(); + CreateMap(); } } } diff --git a/ASI.Basecode.WebApp/Startup.DI.cs b/ASI.Basecode.WebApp/Startup.DI.cs index e0552dc..3eb591f 100644 --- a/ASI.Basecode.WebApp/Startup.DI.cs +++ b/ASI.Basecode.WebApp/Startup.DI.cs @@ -35,10 +35,12 @@ private void ConfigureOtherServices() // Services this._services.TryAddSingleton(); this._services.AddScoped(); + this._services.AddSingleton(); // Repositories this._services.AddScoped(); + this._services.AddSingleton(); // Manager Class this._services.AddScoped(); diff --git a/ASI.Basecode.WebApp/Startup.cs b/ASI.Basecode.WebApp/Startup.cs index a997939..a42d089 100644 --- a/ASI.Basecode.WebApp/Startup.cs +++ b/ASI.Basecode.WebApp/Startup.cs @@ -119,6 +119,15 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton( new PhysicalFileProvider( Path.Combine(Directory.GetCurrentDirectory(), "wwwroot"))); + + + //gi add ni for session services + services.AddSession(options => + { + options.IdleTimeout = TimeSpan.FromMinutes(30); + options.Cookie.HttpOnly = true; + options.Cookie.IsEssential = true; + }); } /// @@ -152,6 +161,9 @@ public void ConfigureApp(IApplicationBuilder app, IWebHostEnvironment env) this._app.UseAuthentication(); this._app.UseAuthorization(); + + //for session use + this._app.UseSession(); } } } diff --git a/ASI.Basecode.WebApp/Views/Account/Login.cshtml b/ASI.Basecode.WebApp/Views/Account/Login.cshtml index 0cee338..1de4897 100644 --- a/ASI.Basecode.WebApp/Views/Account/Login.cshtml +++ b/ASI.Basecode.WebApp/Views/Account/Login.cshtml @@ -58,6 +58,7 @@ + @section scripts { -} \ No newline at end of file +} diff --git a/ASI.Basecode.WebApp/Views/Admin/AdminSettings.cshtml b/ASI.Basecode.WebApp/Views/Admin/AdminSettings.cshtml new file mode 100644 index 0000000..4928098 --- /dev/null +++ b/ASI.Basecode.WebApp/Views/Admin/AdminSettings.cshtml @@ -0,0 +1,38 @@ +@{ + ViewData["Title"] = "Admin Settings"; +} + + +
+
+
+
+

Settings Preferences

+ +
+
+ + Categories +
+
+ + +
+
+ + + + + 8 + + + + +
+ +
+
+
+ \ No newline at end of file diff --git a/ASI.Basecode.WebApp/Views/Admin/Analytics.cshtml b/ASI.Basecode.WebApp/Views/Admin/Analytics.cshtml new file mode 100644 index 0000000..b14ff3e --- /dev/null +++ b/ASI.Basecode.WebApp/Views/Admin/Analytics.cshtml @@ -0,0 +1,63 @@ +@{ + ViewData["Title"] = "Analytics"; +} +
+
+

Report and Analytics

+ +
+
+ +@section Styles { + +} \ No newline at end of file diff --git a/ASI.Basecode.WebApp/Views/Admin/CreateRoom.cshtml b/ASI.Basecode.WebApp/Views/Admin/CreateRoom.cshtml new file mode 100644 index 0000000..0346564 --- /dev/null +++ b/ASI.Basecode.WebApp/Views/Admin/CreateRoom.cshtml @@ -0,0 +1,83 @@ +@model ASI.Basecode.Services.ServiceModels.RoomManagementViewModel +@{ + +} + +
+ + + +
+ +@section Scripts { + @{ + await Html.RenderPartialAsync("_ValidationScriptsPartial"); + } + + + } + diff --git a/ASI.Basecode.WebApp/Views/Admin/Index.cshtml b/ASI.Basecode.WebApp/Views/Admin/Index.cshtml new file mode 100644 index 0000000..7f7bf9f --- /dev/null +++ b/ASI.Basecode.WebApp/Views/Admin/Index.cshtml @@ -0,0 +1,75 @@ +@*@{ + ViewData["Title"] = "Admin Home Page"; +} +
+
+

Admin Home

+ +
+
+ +@section Styles { + +}*@ + +@{ + ViewData["Title"] = "Admin Page"; +} + +
+
+
+

Welcome

+

Learn about building Web apps with ASP.NET Core ADMIN.

+
+
+
diff --git a/ASI.Basecode.WebApp/Views/Admin/ManageRoles.cshtml b/ASI.Basecode.WebApp/Views/Admin/ManageRoles.cshtml new file mode 100644 index 0000000..50b6ae8 --- /dev/null +++ b/ASI.Basecode.WebApp/Views/Admin/ManageRoles.cshtml @@ -0,0 +1,64 @@ +@{ + ViewData["Title"] = "Manage Roles"; +} +
+
+

Manage Roles

+ +
+
+ +@section Styles { + +} \ No newline at end of file diff --git a/ASI.Basecode.WebApp/Views/Admin/RoomManagement.cshtml b/ASI.Basecode.WebApp/Views/Admin/RoomManagement.cshtml new file mode 100644 index 0000000..c9686a5 --- /dev/null +++ b/ASI.Basecode.WebApp/Views/Admin/RoomManagement.cshtml @@ -0,0 +1,190 @@ +@model IEnumerable +@{ + ViewData["Title"] = "Room Management"; +} + + +
+
+
+
+

Room Management

+
+
+ +
+ + + +
+ +
+
+
+

Room Details

+ + + +
+ +
+
+ +
+ +
+ + + +
+ + +
+ + + + + + + + + + + + + + + @foreach (var room in Model) + { + + + + + + + + + + + } + +
SelectIDTypeCodeNameEquipmentsLocationCapacity
+ + @room.RoomId@room.RoomType@room.RoomCode@room.RoomName@room.HasEquipments@room.RoomLocation@room.RoomCapacity
+
+
+
+
+ + + + + + + + +@section Scripts { + +} + diff --git a/ASI.Basecode.WebApp/Views/Home/Calendar.cshtml b/ASI.Basecode.WebApp/Views/Home/Calendar.cshtml new file mode 100644 index 0000000..3d2b2fc --- /dev/null +++ b/ASI.Basecode.WebApp/Views/Home/Calendar.cshtml @@ -0,0 +1,63 @@ +@{ + ViewData["Title"] = "Calendar"; +} +
+
+

Calendar

+ +
+
+ +@section Styles { + +} \ No newline at end of file diff --git a/ASI.Basecode.WebApp/Views/Home/Index.cshtml b/ASI.Basecode.WebApp/Views/Home/Index.cshtml index d2d19bd..0a8353d 100644 --- a/ASI.Basecode.WebApp/Views/Home/Index.cshtml +++ b/ASI.Basecode.WebApp/Views/Home/Index.cshtml @@ -1,8 +1,500 @@ @{ - ViewData["Title"] = "Home Page"; + ViewData["Title"] = "User Home Page"; } +
+
+
+
+ + Add Booking +
+
+ + My Bookings +
+
+
+
+
+
+
+ 11:11
+ Tuesday, June 18 +
+
+ +
+
+
+
+
+
+

Today's Booking

+
+ 09:00 + Project Management Mock Defense + Training Room +
+
+ 11:00 + C# Mock Defense + Training Room +
+
+
+
+ +
+
+ + + *@ \ No newline at end of file diff --git a/ASI.Basecode.WebApp/Views/Shared/_Layout.cshtml b/ASI.Basecode.WebApp/Views/Shared/_Layout.cshtml index cf2c918..b19fd76 100644 --- a/ASI.Basecode.WebApp/Views/Shared/_Layout.cshtml +++ b/ASI.Basecode.WebApp/Views/Shared/_Layout.cshtml @@ -1,6 +1,4 @@ -@using static ASI.Basecode.Resources.Views.Screen - - + @@ -11,21 +9,127 @@ + + + + @if (Context.Session.GetString("UserRole") == "Admin") + { + + + } + @RenderSection("Styles", required: false) @Html.Partial("_Header") -
+ + @{ + var isAdmin = Context.Session.GetString("UserRole") == "Admin"; + var isLoginOrRegister = ViewContext.RouteData.Values["Controller"].ToString() == "Account" && + (ViewContext.RouteData.Values["Action"].ToString() == "Login" || + ViewContext.RouteData.Values["Action"].ToString() == "Register"); + } + + @if (!isLoginOrRegister) + { + @if (isAdmin) + { + @Html.Partial("_AdminSidebar") + } + else + { + @Html.Partial("_UserSidebar") + } + } + +
@RenderBody()
-
-
- @Copyright -
-
+ + + + + + + + + + + + + @await RenderSectionAsync("Scripts", required: false) + + + + +@* + + + + + @ViewData["Title"] + + + + + + + + + + + + + @RenderSection("Styles", required: false) + + + @Html.Partial("_Header") + @{ + + var isAdmin = Context.Session.GetString("UserRole") == "Admin"; + var isLoginOrRegister = ViewContext.RouteData.Values["Controller"].ToString() == "Account" && + (ViewContext.RouteData.Values["Action"].ToString() == "Login" || + ViewContext.RouteData.Values["Action"].ToString() == "Register"); + } + + @if (!isLoginOrRegister) + { + if (isAdmin) + { + + + + + @Html.Partial("_AdminSidebar") + + } + else + { + @Html.Partial("_UserSidebar") + } + } + +
+
+ @RenderBody() +
+
+ @@ -34,15 +138,32 @@ + + + @await RenderSectionAsync("Scripts", required: false) +*@ diff --git a/ASI.Basecode.WebApp/Views/Shared/_UserSidebar.cshtml b/ASI.Basecode.WebApp/Views/Shared/_UserSidebar.cshtml new file mode 100644 index 0000000..aae0464 --- /dev/null +++ b/ASI.Basecode.WebApp/Views/Shared/_UserSidebar.cshtml @@ -0,0 +1,175 @@ +@* + For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 +*@ +@{ + +} + + diff --git a/ASI.Basecode.WebApp/wwwroot/css/adminsidebar.css b/ASI.Basecode.WebApp/wwwroot/css/adminsidebar.css new file mode 100644 index 0000000..5d101ca --- /dev/null +++ b/ASI.Basecode.WebApp/wwwroot/css/adminsidebar.css @@ -0,0 +1,609 @@ +:root { + --light: #f0f0f0; + --dark: #333; + --grey: #ddd; + --light-blue: #cce5ff; + --blue: #007bff; + --light-yellow: #fff3cd; + --yellow: #ffc107; + --light-orange: #ffe5b4; + --orange: #fd7e14; +} +/* Sidebar styles */ +.sidebar { + width: 60px; + height: 100%; + background-color: #000; + color: #fff; + position: fixed; + display: flex; + flex-direction: column; + align-items: center; + padding-top: 10px; + z-index: 1; + transition: width 0.3s ease, left 0.3s ease; + font-size: 11px; +} + +.sidebar.expanded { + width: 185px; + font-size: 11px; +} +.sidebar .p { + width: 0px; + height: 100%; + background-color: #000; + color: #000; + transition: width 0.3s ease, left 0.3s ease; + font-size: 10px; + +} + + + +.sidebar .logo img { + align-items: center; + + font-size: 11px; + text-align: hidden; + width: 30px; + height: 20px; + transition: width 0.3s ease; /* smooth transition */ +} + +.sidebar.expanded .logo img { + width: 50px; /* expanded width */ + align-items: center; + font-size: 11px; +} + +.sidebar-menu { + list-style: none; + padding: 0; + margin: 25px 0; + width: 100%; +} + +.sidebar-menu li { + width: 100%; +} + +.sidebar-menu li a { + display: flex; + align-items: center; + padding: 15px 20px; + color: #fff; + text-decoration: none; + width: 100%; + transition: background-color 0.3s ease, color 0.3s ease; /* smooth transitions */ +} + +.sidebar-menu li a:hover { + background-color: #333; /* hover color */ +} + +.sidebar-menu li.active a { + background-color: lightblue; /* selected button background color */ + color: black; /* text color */ + font-weight: bold; /* make text bold */ +} + +.sidebar-menu li a i { + margin-right: 10px; /* margin for icons */ + transition: margin-right 0.3s ease, opacity 0.3s ease; /* smooth transition */ + opacity: 1; /* initially visible */ +} + +.sidebar-menu li a:hover i { + margin-right: 15px; /* adjust margin on hover */ +} + +.sidebar-menu li a span { + display: none; + transition: display 0.3s ease; /* smooth transition */ +} + +.sidebar.expanded .sidebar-menu li a span { + display: inline; /* display text on expansion */ +} + +.user-info { + margin-top: auto; + width: 100%; + padding: 10px; + display: flex; + align-items: center; + justify-content: space-between; +} + +.notification-button { + position: relative; +} + +.notification-button a { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + background-color: #333; + border-radius: 50%; + color: #fff; + text-decoration: none; + transition: background-color 0.3s ease; +} + +.notification-button a:hover { + background-color: #555; +} + +.notification-badge { + position: absolute; + top: -5px; + right: -5px; + background-color: #ff4444; + color: #fff; + font-size: 12px; + font-weight: bold; + padding: 2px 6px; + border-radius: 50%; +} + +.user-details { + flex-grow: 1; + margin-left: 15px; + display: none; + flex-direction: column; + align-items: flex-start; +} + +.sidebar.expanded .user-details { + display: flex; +} + +.user-name { + font-weight: bold; + margin-bottom: 5px; +} + +.user-email { + font-size: 0.7em; + color: #bbb; +} + +.logout a { + display: flex; + align-items: center; + color: #fff; + text-decoration: none; +} + + .logout a i { + font-size: 1.4em; + } + + +.sidebar.expanded ~ .outer-container { + margin-left: 185px; +} + +.outer-container ~ .sidebar.expanded { + margin-left: 150vh; +} + +body { + background-color: #000; + margin: 0; + font-family: Arial, sans-serif; +} + + +.main-content { + + padding: 20px; + color: #000; + border-radius: 10px; + flex-grow: 1; + max-width: calc(100% -80px); +} + + +h1 { + font-size: 30px; + font-weight: 500; + margin-top: 0; + margin-bottom: 30px; + letter-spacing: 0.5px; +} + + + +.outer-container { + width: 100%; + background-color: var(--light); + padding: 20px; + border-radius: 20px; + display: flex; + flex-direction: column-reverse; + flex-direction: column; + width: calc(100% - 185px); + height: 100vh; + top: 20px; + right: 0px; + bottom: 10px; + padding-top: 20px; + margin-left: 100px; + position: fixed; + z-index: 0; + transition: margin-right 0.3s ease, width 0.3s ease; +} + +.outer-container.expanded { + width: calc(100% - 60px); + height: 100vh; +} + + + +.outer-container { + padding: 20px; + background-color: var(--light); +} + +.main-content { + background-color: var(--light); + padding: 20px; + border-radius: 10px; +} + +/* Head Title */ +.main-content .head-title { + display: flex; + font-weight: bold; + align-items: center; + justify-content: space-between; + grid-gap: 6px; + flex-wrap: wrap; + background-color: lightblue; + align-content: center; + padding: 10px; + color: #fff; + flex-grow: 1; + max-width: calc(100% - 80px); +} + +.outer-container .head-title { + display: flex; + align-items: center; + text-align: center; + justify-content: space-between; + grid-gap: 6px; + flex-wrap: wrap; +} + +.outer-container .head-title .left h1 { + font-size: 36px; + font-weight: 600; + margin-bottom: 10px; + color: var(--dark); +} + +//////////////// +/* Floor Buttons */ +.outer-container button{ + display: grid; + background-color: var(--light); + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); + grid-gap: 24px; + margin-top: 16px; + align-items: center; + justify-content: center; +} + +.floor-buttons button { + background-color: var(--blue); + color: var(--dark); + padding: 10px; + margin-top: 10px; + margin-left: 10px; + margin-right: 10px; + align-items: center; + justify-content: center; + gap: 10px; + border: none; + border-radius: 5px; + text-align: center; + transition: background-color 0.3s; +} + + + + .floor-buttons button i { + color: var(--dark); + border-radius: 5px; + font-size: 20px; + justify-content: center; + align-items: center; + height: 40px + } + +.floor-buttons button span { + align-items: center; + width: 200px; + + +} + +.floor-buttons button:hover { + background-color: var(--grey); +} + + +/* Room Details Table */ +.table-data { + display: flex; + flex-wrap: wrap; + grid-gap: 24px; + margin-top: 24px; + width: 100%; + color: var(--dark); +} + + .table-data > div { + border-radius: 20px; + background: var(--light); + padding: 24px; + overflow-x: auto; + } + + .table-data .head { + display: flex; + align-items: center; + grid-gap: 16px; + margin-bottom: 24px; + } + .table-data .add-room { + background-color: var(--blue); + border-radius: 5px; + font-size: 10px; + } + .table-data .add-room a{ + border-radius: 5px; + font-size: 10px; + } + + .table-data .head h3 { + margin-right: auto; + font-size: 24px; + font-weight: 600; + } + + .table-data .order { + flex-grow: 1; + flex-basis: 500px; + } + + .table-data .order table { + width: 100%; + border-collapse: collapse; + } + + .table-data .order table th { + padding-bottom: 12px; + font-size: 13px; + text-align: left; + border-bottom: 1px solid var(--grey); + } + + .table-data .order table td { + padding: 16px 0; + } + + .table-data .order table tr td:first-child { + display: flex; + align-items: center; + grid-gap: 12px; + padding-left: 6px; + } + + .table-data .order table td img { + width: 36px; + height: 36px; + border-radius: 50%; + object-fit: cover; + } + + .table-data .order table tbody tr:hover { + background: var(--grey); + } + + + +/*AddROOM WINDOW*/ +.add-container { + background-color: rgba(0, 0, 0, 0.5); /* semi-transparent black for the background blur effect */ + width: 100%; + height: 100%; + position: fixed; + top: 0; + left: 0; + display: flex; + justify-content: center; + align-items: center; + z-index: 9999; /* ensure it's above other content */ +} + +.modal-create { + background-color: var(--light-blue); /* your modal background color */ + padding: 20px; + border-radius: 20px; + width: 80%; + max-width: 600px; + text-align: left; + margin-right: 185px; + margin-left:185px; +} + + + + + + + + + + + + + + + + + + + + + +/*SETTINGS*/ +.outer-container .mode { + height: 56px; + background: /*var(--grey)*/grey; + padding: 0 24px; + display: flex; + align-items: center; + grid-gap: 24px; + font-family: var(--lato); + position: sticky; + top: 0; + left: 0; + z-index: 1000; +} + +/* + .outer-container .mode::before { + content: ''; + position: absolute; + width: 40px; + height: 40px; + bottom: -40px; + left: 0; + border-radius: 50%; + box-shadow: -20px -20px 0 var(--light); + }*/ + + .outer-container .mode a { + color: var(--dark); + } + + .outer-container .mode .bx.bx-menu { + cursor: pointer; + color: var(--dark); + } + + .outer-container .mode .nav-link { + font-size: 16px; + transition: .3s ease; + } + + .outer-container .mode .nav-link:hover { + color: var(--blue); + } + + .outer-container .mode form { + max-width: 400px; + width: 100%; + margin-right: auto; + } + +.outer-container .mode form .form-input { + display: flex; + align-items: center; + height: 36px; +} + +.outer-container .mode form .form-input input { + flex-grow: 1; + padding: 0 16px; + height: 100%; + border: none; + background: var(--grey); + border-radius: 36px 0 0 36px; + outline: none; + width: 100%; + color: var(--dark); +} + +.outer-container .mode form .form-input button { + width: 36px; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + background: var(--blue); + color: var(--light); + font-size: 18px; + border: none; + outline: none; + border-radius: 0 36px 36px 0; + cursor: pointer; +} + + .outer-container .mode .notification { + font-size: 20px; + position: relative; + } + + .outer-container .mode .notification .num { + position: absolute; + top: -6px; + right: -6px; + width: 20px; + height: 20px; + border-radius: 50%; + border: 2px solid var(--light); + background: var(--red); + color: var(--light); + font-weight: 700; + font-size: 12px; + display: flex; + justify-content: center; + align-items: center; + } + + .outer-container .mode .profile img { + width: 36px; + height: 36px; + object-fit: cover; + border-radius: 50%; + } + + +.main-content .mode .switch-mode { + display: block; + min-width: 50px; + height: 25px; + border-radius: 25px; + background: /*var(--grey)*/ grey; + cursor: pointer; + position: relative; +} + +.main-content .mode .switch-mode::before { + content: ''; + position: absolute; + top: 2px; + left: 2px; + bottom: 2px; + width: calc(25px - 4px); + background: /*var(--blue)*/blue; + border-radius: 50%; + transition: all .3s ease; +} + +.outer-container .mode .switch-mode:checked + .switch-mode::before { + left: calc(100% - (25px - 4px) - 2px); +} +/* NAVBAR */ + + + diff --git a/ASI.Basecode.WebApp/wwwroot/css/login.css b/ASI.Basecode.WebApp/wwwroot/css/login.css index fad2ab1..8f77476 100644 --- a/ASI.Basecode.WebApp/wwwroot/css/login.css +++ b/ASI.Basecode.WebApp/wwwroot/css/login.css @@ -27,3 +27,6 @@ border-bottom-right-radius: .3rem; } } + body{ + background-color: #fff; + } \ No newline at end of file diff --git a/ASI.Basecode.WebApp/wwwroot/css/main.css b/ASI.Basecode.WebApp/wwwroot/css/main.css index 1e6744c..5f28270 100644 --- a/ASI.Basecode.WebApp/wwwroot/css/main.css +++ b/ASI.Basecode.WebApp/wwwroot/css/main.css @@ -1,16 +1 @@ -.footer { - -moz-transition: all 0.3s ease-in-out; - -o-transition: all 0.3s ease-in-out; - -webkit-transition: all 0.3s ease-in-out; - transition: all 0.3s ease-in-out; - position: absolute; - left: 0; - right: 0; - height: 64px; - line-height: 64px; - vertical-align: middle; - bottom: 0; - /* padding: 10px; */ - font-size: 0.9em; - text-align: center; -} + \ No newline at end of file diff --git a/ASI.Basecode.WebApp/wwwroot/css/site.css b/ASI.Basecode.WebApp/wwwroot/css/site.css index d3f4a7a..18ba538 100644 --- a/ASI.Basecode.WebApp/wwwroot/css/site.css +++ b/ASI.Basecode.WebApp/wwwroot/css/site.css @@ -17,7 +17,8 @@ html { min-height: 100%; } -body { +body .outer-container { + background-color: #fff; margin-bottom: 60px; } @@ -84,4 +85,7 @@ body { .w-1000px { width: 1000px; -} \ No newline at end of file +} + + + diff --git a/ASI.Basecode.WebApp/wwwroot/css/style.css b/ASI.Basecode.WebApp/wwwroot/css/style.css index 05d1acd..1758c8a 100644 --- a/ASI.Basecode.WebApp/wwwroot/css/style.css +++ b/ASI.Basecode.WebApp/wwwroot/css/style.css @@ -22,7 +22,7 @@ } body { - background-color: var(--background-color4); + background-color: black; max-width: 100%; overflow-x: hidden; } diff --git a/ASI.Basecode.WebApp/wwwroot/img/book.jpg b/ASI.Basecode.WebApp/wwwroot/img/book.jpg new file mode 100644 index 0000000..89442ac Binary files /dev/null and b/ASI.Basecode.WebApp/wwwroot/img/book.jpg differ diff --git a/ASI.Basecode.WebApp/wwwroot/js/adminsidebar.js b/ASI.Basecode.WebApp/wwwroot/js/adminsidebar.js new file mode 100644 index 0000000..ec77cb8 --- /dev/null +++ b/ASI.Basecode.WebApp/wwwroot/js/adminsidebar.js @@ -0,0 +1,98 @@ + + + + + + + + + + + +/* + + + +const allSideMenu = document.querySelectorAll('#sidebar .side-menu.top li a'); + +allSideMenu.forEach(item => { + const li = item.parentElement; + + item.addEventListener('click', function () { + allSideMenu.forEach(i => { + i.parentElement.classList.remove('active'); + }) + li.classList.add('active'); + }) +});*/ +/* + +document.addEventListener('DOMContentLoaded', function () { + const sidebar = document.querySelector('.sidebar'); + const outerContainer = document.querySelector('.outer-container'); + + sidebar.addEventListener('click', function () { + sidebar.classList.toggle('hidden'); + outerContainer.classList.toggle('expanded'); + }); +}); +*/ +/* + + +// TOGGLE SIDEBAR +const menuBar = document.querySelector('#content nav .bx.bx-menu'); +const sidebar = document.getElementById('sidebar'); + +menuBar.addEventListener('click', function () { + sidebar.classList.toggle('hide'); +}) + + + + +const searchButton = document.querySelector('#content nav form .form-input button'); +const searchButtonIcon = document.querySelector('#content nav form .form-input button .bx'); +const searchForm = document.querySelector('#content nav form'); + +searchButton.addEventListener('click', function (e) { + if (window.innerWidth < 576) { + e.preventDefault(); + searchForm.classList.toggle('show'); + if (searchForm.classList.contains('show')) { + searchButtonIcon.classList.replace('bx-search', 'bx-x'); + } else { + searchButtonIcon.classList.replace('bx-x', 'bx-search'); + } + } +}) + + + + +if (window.innerWidth < 768) { + sidebar.classList.add('hide'); +} else if (window.innerWidth > 576) { + searchButtonIcon.classList.replace('bx-x', 'bx-search'); + searchForm.classList.remove('show'); +} + + +window.addEventListener('resize', function () { + if (this.innerWidth > 576) { + searchButtonIcon.classList.replace('bx-x', 'bx-search'); + searchForm.classList.remove('show'); + } +}) +*/ +/* + +const switchMode = document.getElementById('switch-mode'); + +switchMode.addEventListener('change', function () { + if (this.checked) { + document.body.classList.add('dark'); + } else { + document.body.classList.remove('dark'); + } +})*/ \ No newline at end of file diff --git a/ASI.Basecode.WebApp/wwwroot/js/site.js b/ASI.Basecode.WebApp/wwwroot/js/site.js index 0ef2adb..da4f9b0 100644 --- a/ASI.Basecode.WebApp/wwwroot/js/site.js +++ b/ASI.Basecode.WebApp/wwwroot/js/site.js @@ -1,6 +1,6 @@ -let dpicn = document.querySelector(".dpicn"); +/*let dpicn = document.querySelector(".dpicn"); let dropdown = document.querySelector(".dropdown"); dpicn.addEventListener("click", () => { dropdown.classList.toggle("dropdown-open"); -}) \ No newline at end of file +})*/ \ No newline at end of file diff --git a/ASI.Basecode.sln b/ASI.Basecode.sln index e20a71f..732d818 100644 --- a/ASI.Basecode.sln +++ b/ASI.Basecode.sln @@ -11,7 +11,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASI.Basecode.Services", "AS EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{65A10F5F-9790-475E-A544-DF3FF6A41A66}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ASI.Basecode.Resources", "ASI.Basecode.Resources\ASI.Basecode.Resources.csproj", "{ED0C96A6-749E-413B-BF4D-8E405BEB172E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASI.Basecode.Resources", "ASI.Basecode.Resources\ASI.Basecode.Resources.csproj", "{ED0C96A6-749E-413B-BF4D-8E405BEB172E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution