├── Spice ├── Views │ ├── _ViewStart.cshtml │ ├── _ViewImports.cshtml │ └── Shared │ │ ├── Components │ │ └── UserName │ │ │ └── Default.cshtml │ │ ├── _CreateButtonPartial.cshtml │ │ ├── _CreateAndBackToListButton.cshtml │ │ ├── _DeleteAndBackToListButton.cshtml │ │ ├── _EditAndBackToListButton.cshtml │ │ ├── _DetailsAndBackToListButton.cshtml │ │ ├── _StatusMessage.cshtml │ │ ├── _OrderStatus.cshtml │ │ ├── _TableButtonPartial.cshtml │ │ ├── Error.cshtml │ │ ├── _LoginPartial.cshtml │ │ ├── _CookieConsentPartial.cshtml │ │ ├── _ValidationScriptsPartial.cshtml │ │ └── _ThumbnailAreaPArtial.cshtml ├── Areas │ ├── Identity │ │ ├── Pages │ │ │ ├── Account │ │ │ │ ├── _ViewImports.cshtml │ │ │ │ ├── Manage │ │ │ │ │ ├── _ViewImports.cshtml │ │ │ │ │ ├── DownloadPersonalData.cshtml │ │ │ │ │ ├── _StatusMessage.cshtml │ │ │ │ │ ├── _Layout.cshtml │ │ │ │ │ ├── Disable2fa.cshtml │ │ │ │ │ ├── PersonalData.cshtml │ │ │ │ │ ├── ResetAuthenticator.cshtml │ │ │ │ │ ├── PersonalData.cshtml.cs │ │ │ │ │ ├── GenerateRecoveryCodes.cshtml │ │ │ │ │ ├── _ManageNav.cshtml │ │ │ │ │ ├── DeletePersonalData.cshtml │ │ │ │ │ ├── SetPassword.cshtml │ │ │ │ │ ├── ChangePassword.cshtml │ │ │ │ │ ├── ManageNavPages.cs │ │ │ │ │ ├── Index.cshtml │ │ │ │ │ ├── DownloadPersonalData.cshtml.cs │ │ │ │ │ ├── ExternalLogins.cshtml │ │ │ │ │ ├── TwoFactorAuthentication.cshtml │ │ │ │ │ ├── ResetAuthenticator.cshtml.cs │ │ │ │ │ ├── Disable2fa.cshtml.cs │ │ │ │ │ ├── TwoFactorAuthentication.cshtml.cs │ │ │ │ │ ├── GenerateRecoveryCodes.cshtml.cs │ │ │ │ │ ├── DeletePersonalData.cshtml.cs │ │ │ │ │ ├── EnableAuthenticator.cshtml │ │ │ │ │ ├── SetPassword.cshtml.cs │ │ │ │ │ └── ChangePassword.cshtml.cs │ │ │ │ ├── Logout.cshtml │ │ │ │ ├── ConfirmEmail.cshtml │ │ │ │ ├── ForgotPasswordConfirmation.cshtml │ │ │ │ ├── AccessDenied.cshtml │ │ │ │ ├── Lockout.cshtml │ │ │ │ ├── ResetPasswordConfirmation.cshtml │ │ │ │ ├── AccessDenied.cshtml.cs │ │ │ │ ├── ForgotPasswordConfirmation.cshtml.cs │ │ │ │ ├── Lockout.cshtml.cs │ │ │ │ ├── ResetPasswordConfirmation.cshtml.cs │ │ │ │ ├── ForgotPassword.cshtml │ │ │ │ ├── LoginWithRecoveryCode.cshtml │ │ │ │ ├── ConfirmEmail.cshtml.cs │ │ │ │ ├── Logout.cshtml.cs │ │ │ │ ├── ResetPassword.cshtml │ │ │ │ ├── LoginWith2fa.cshtml │ │ │ │ ├── ForgotPassword.cshtml.cs │ │ │ │ ├── ResetPassword.cshtml.cs │ │ │ │ ├── LoginWithRecoveryCode.cshtml.cs │ │ │ │ ├── Login.cshtml │ │ │ │ └── LoginWith2fa.cshtml.cs │ │ │ ├── _ViewStart.cshtml │ │ │ ├── _ViewImports.cshtml │ │ │ ├── Error.cshtml.cs │ │ │ ├── Error.cshtml │ │ │ └── _ValidationScriptsPartial.cshtml │ │ └── IdentityHostingStartup.cs │ ├── Admin │ │ ├── Views │ │ │ ├── _ViewStart.cshtml │ │ │ ├── _ViewImports.cshtml │ │ │ ├── Category │ │ │ │ ├── Details.cshtml │ │ │ │ ├── Delete.cshtml │ │ │ │ ├── Create.cshtml │ │ │ │ ├── Edit.cshtml │ │ │ │ └── Index.cshtml │ │ │ ├── SubCategory │ │ │ │ ├── Details.cshtml │ │ │ │ ├── Delete.cshtml │ │ │ │ ├── Index.cshtml │ │ │ │ ├── Create.cshtml │ │ │ │ └── Edit.cshtml │ │ │ ├── MenuItem │ │ │ │ ├── Index.cshtml │ │ │ │ ├── Details.cshtml │ │ │ │ └── Delete.cshtml │ │ │ ├── Coupon │ │ │ │ ├── Index.cshtml │ │ │ │ ├── Details.cshtml │ │ │ │ ├── Create.cshtml │ │ │ │ ├── Delete.cshtml │ │ │ │ └── Edit.cshtml │ │ │ └── User │ │ │ │ └── Index.cshtml │ │ └── Controllers │ │ │ ├── UserController.cs │ │ │ └── CategoryController.cs │ └── Customer │ │ └── Views │ │ ├── _ViewStart.cshtml │ │ ├── _ViewImports.cshtml │ │ ├── Home │ │ ├── Privacy.cshtml │ │ └── Index.cshtml │ │ └── Order │ │ └── Confirm.cshtml ├── wwwroot │ ├── favicon.ico │ ├── images │ │ ├── 1.jpg │ │ ├── 10.jpg │ │ ├── 3.jpg │ │ ├── 4.jpg │ │ ├── 5.jpg │ │ ├── 6.jpg │ │ ├── 7.jpg │ │ ├── 8.jpeg │ │ ├── 9.jpg │ │ ├── mild.png │ │ ├── 15OFF.png │ │ ├── 20OFF.png │ │ ├── spicy.png │ │ ├── InKitchen.png │ │ ├── completed.png │ │ ├── verySpicy.png │ │ ├── OrderPlaced.png │ │ ├── default_food.png │ │ ├── ReadyForPickup.png │ │ └── dust_scratches.png │ ├── css │ │ ├── images │ │ │ ├── ui-icons_444444_256x240.png │ │ │ ├── ui-icons_555555_256x240.png │ │ │ ├── ui-icons_777620_256x240.png │ │ │ ├── ui-icons_777777_256x240.png │ │ │ ├── ui-icons_cc0000_256x240.png │ │ │ └── ui-icons_ffffff_256x240.png │ │ └── site.css │ ├── js │ │ └── site.js │ └── lib │ │ ├── jquery-validation-unobtrusive │ │ └── LICENSE.txt │ │ ├── jquery-validation │ │ └── LICENSE.md │ │ ├── bootstrap │ │ ├── LICENSE │ │ └── dist │ │ │ └── css │ │ │ └── bootstrap-reboot.min.css │ │ └── jquery │ │ └── LICENSE.txt ├── appsettings.Development.json ├── Data │ ├── IDbInitializer.cs │ ├── ApplicationDbContext.cs │ ├── Migrations │ │ ├── 20181206183855_addCategoryToDatabase.cs │ │ ├── 20181209071258_AddCouponToDatabase.cs │ │ ├── 20181208181334_addSubCategoryToDatabase.cs │ │ ├── 20181209210635_AddMoreFieldsToIdentityUser.cs │ │ ├── 20181209035249_AddMenuItemToDatabase.cs │ │ └── 20181212202216_AddShoppingCartToDb.cs │ └── DbInitializer.cs ├── Models │ ├── ErrorViewModel.cs │ ├── ViewModels │ │ ├── OrderDetailsCart.cs │ │ ├── OrderListViewModel.cs │ │ ├── OrderDetailsViewModel.cs │ │ ├── MenuItemViewModel.cs │ │ ├── IndexViewModel.cs │ │ └── SubCategoryAndCategoryViewModel.cs │ ├── Category.cs │ ├── PagingInfo.cs │ ├── ApplicationUser.cs │ ├── SubCategory.cs │ ├── Coupon.cs │ ├── OrderDetails.cs │ ├── ShoppingCart.cs │ ├── MenuItem.cs │ └── OrderHeader.cs ├── Service │ ├── EmailOptions.cs │ └── EmailSender.cs ├── Utility │ ├── StripeSettings.cs │ └── SD.cs ├── Extensions │ ├── ReflectionExtension.cs │ └── IEnumerableExtension.cs ├── appsettings.json ├── Program.cs ├── Properties │ ├── launchSettings.json │ └── PublishProfiles │ │ ├── FolderProfile.pubxml │ │ └── Spice20190104024839 - Web Deploy.pubxml ├── ScaffoldingReadMe.txt ├── ViewComponenets │ └── UserNameViewComponent.cs ├── Spice.csproj └── TagHelpers │ └── PageLinkTagHelper.cs ├── Spice.sln └── .gitattributes /Spice/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using Spice.Areas.Identity.Pages.Account -------------------------------------------------------------------------------- /Spice/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/favicon.ico -------------------------------------------------------------------------------- /Spice/wwwroot/images/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/1.jpg -------------------------------------------------------------------------------- /Spice/wwwroot/images/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/10.jpg -------------------------------------------------------------------------------- /Spice/wwwroot/images/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/3.jpg -------------------------------------------------------------------------------- /Spice/wwwroot/images/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/4.jpg -------------------------------------------------------------------------------- /Spice/wwwroot/images/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/5.jpg -------------------------------------------------------------------------------- /Spice/wwwroot/images/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/6.jpg -------------------------------------------------------------------------------- /Spice/wwwroot/images/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/7.jpg -------------------------------------------------------------------------------- /Spice/wwwroot/images/8.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/8.jpeg -------------------------------------------------------------------------------- /Spice/wwwroot/images/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/9.jpg -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /Spice/Areas/Customer/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /Spice/wwwroot/images/mild.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/mild.png -------------------------------------------------------------------------------- /Spice/wwwroot/images/15OFF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/15OFF.png -------------------------------------------------------------------------------- /Spice/wwwroot/images/20OFF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/20OFF.png -------------------------------------------------------------------------------- /Spice/wwwroot/images/spicy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/spicy.png -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using Spice.Areas.Identity.Pages.Account.Manage 2 | -------------------------------------------------------------------------------- /Spice/wwwroot/images/InKitchen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/InKitchen.png -------------------------------------------------------------------------------- /Spice/wwwroot/images/completed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/completed.png -------------------------------------------------------------------------------- /Spice/wwwroot/images/verySpicy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/verySpicy.png -------------------------------------------------------------------------------- /Spice/wwwroot/images/OrderPlaced.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/OrderPlaced.png -------------------------------------------------------------------------------- /Spice/wwwroot/images/default_food.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/default_food.png -------------------------------------------------------------------------------- /Spice/wwwroot/images/ReadyForPickup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/ReadyForPickup.png -------------------------------------------------------------------------------- /Spice/wwwroot/images/dust_scratches.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/images/dust_scratches.png -------------------------------------------------------------------------------- /Spice/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using Spice 2 | @using Spice.Models 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /Spice/Views/Shared/Components/UserName/Default.cshtml: -------------------------------------------------------------------------------- 1 | @model Spice.Models.ApplicationUser 2 | Hi! @Model.Name -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using Spice 2 | @using Spice.Models 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /Spice/wwwroot/css/images/ui-icons_444444_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/css/images/ui-icons_444444_256x240.png -------------------------------------------------------------------------------- /Spice/wwwroot/css/images/ui-icons_555555_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/css/images/ui-icons_555555_256x240.png -------------------------------------------------------------------------------- /Spice/wwwroot/css/images/ui-icons_777620_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/css/images/ui-icons_777620_256x240.png -------------------------------------------------------------------------------- /Spice/wwwroot/css/images/ui-icons_777777_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/css/images/ui-icons_777777_256x240.png -------------------------------------------------------------------------------- /Spice/wwwroot/css/images/ui-icons_cc0000_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/css/images/ui-icons_cc0000_256x240.png -------------------------------------------------------------------------------- /Spice/wwwroot/css/images/ui-icons_ffffff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhrugen/Spice/HEAD/Spice/wwwroot/css/images/ui-icons_ffffff_256x240.png -------------------------------------------------------------------------------- /Spice/Views/Shared/_CreateButtonPartial.cshtml: -------------------------------------------------------------------------------- 1 |

2 |   Create New 3 |

-------------------------------------------------------------------------------- /Spice/Areas/Customer/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using Spice 2 | @using Spice.Models 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | @addTagHelper Spice.TagHelpers.*, Spice 5 | -------------------------------------------------------------------------------- /Spice/Areas/Customer/Views/Home/Privacy.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Privacy Policy"; 3 | } 4 |

@ViewData["Title"]

5 | 6 |

Use this page to detail your site's privacy policy.

7 | -------------------------------------------------------------------------------- /Spice/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Identity 2 | @using Spice.Areas.Identity 3 | @using Microsoft.AspNetCore.Identity 4 | @namespace Spice.Areas.Identity.Pages 5 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 6 | -------------------------------------------------------------------------------- /Spice/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | // for details on configuring this project to bundle and minify static web assets. 3 | 4 | // Write your JavaScript code. 5 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Logout.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model LogoutModel 3 | @{ 4 | ViewData["Title"] = "Log out"; 5 | } 6 | 7 |
8 |

@ViewData["Title"]

9 |

You have successfully logged out of the application.

10 |
-------------------------------------------------------------------------------- /Spice/Data/IDbInitializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Spice.Data 7 | { 8 | public interface IDbInitializer 9 | { 10 | void Initialize(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Spice/Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Spice.Models 4 | { 5 | public class ErrorViewModel 6 | { 7 | public string RequestId { get; set; } 8 | 9 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 10 | } 11 | } -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/ConfirmEmail.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model ConfirmEmailModel 3 | @{ 4 | ViewData["Title"] = "Confirm email"; 5 | } 6 | 7 |

@ViewData["Title"]

8 |
9 |

10 | Thank you for confirming your email. 11 |

12 |
13 | -------------------------------------------------------------------------------- /Spice/Service/EmailOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Spice.Service 7 | { 8 | public class EmailOptions 9 | { 10 | public string SendGridKey { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model ForgotPasswordConfirmation 3 | @{ 4 | ViewData["Title"] = "Forgot password confirmation"; 5 | } 6 | 7 |

@ViewData["Title"]

8 |

9 | Please check your email to reset your password. 10 |

11 | 12 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/AccessDenied.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model AccessDeniedModel 3 | @{ 4 | ViewData["Title"] = "Access denied"; 5 | } 6 | 7 |
8 |

@ViewData["Title"]

9 |

You do not have access to this resource.

10 |
11 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Lockout.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model LockoutModel 3 | @{ 4 | ViewData["Title"] = "Locked out"; 5 | } 6 | 7 |
8 |

@ViewData["Title"]

9 |

This account has been locked out, please try again later.

10 |
11 | -------------------------------------------------------------------------------- /Spice/Views/Shared/_CreateAndBackToListButton.cshtml: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 | Back to List 7 |
8 |
9 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model ResetPasswordConfirmationModel 3 | @{ 4 | ViewData["Title"] = "Reset password confirmation"; 5 | } 6 | 7 |

@ViewData["Title"]

8 |

9 | Your password has been reset. Please click here to log in. 10 |

11 | -------------------------------------------------------------------------------- /Spice/Utility/StripeSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Spice.Utility 7 | { 8 | public class StripeSettings 9 | { 10 | public string SecretKey { get; set; } 11 | public string PublishableKey { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/DownloadPersonalData.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model DownloadPersonalDataModel 3 | @{ 4 | ViewData["Title"] = "Download Your Data"; 5 | ViewData["ActivePage"] = ManageNavPages.PersonalData; 6 | } 7 | 8 |

@ViewData["Title"]

9 | 10 | @section Scripts { 11 | 12 | } -------------------------------------------------------------------------------- /Spice/Views/Shared/_DeleteAndBackToListButton.cshtml: -------------------------------------------------------------------------------- 1 | @model int 2 | 3 |
4 |
5 | 6 |
7 |
8 | Back to List 9 |
10 |
-------------------------------------------------------------------------------- /Spice/Views/Shared/_EditAndBackToListButton.cshtml: -------------------------------------------------------------------------------- 1 | @model int 2 | 3 |
4 |
5 | 6 |
7 |
8 | Back to List 9 |
10 |
-------------------------------------------------------------------------------- /Spice/Models/ViewModels/OrderDetailsCart.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Spice.Models.ViewModels 7 | { 8 | public class OrderDetailsCart 9 | { 10 | public List listCart { get; set; } 11 | public OrderHeader OrderHeader { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Spice/Views/Shared/_DetailsAndBackToListButton.cshtml: -------------------------------------------------------------------------------- 1 | @model int 2 | 3 | 4 | 5 |
6 |
7 | Edit 8 |
9 |
10 | Back to List 11 |
12 |
13 | 14 | -------------------------------------------------------------------------------- /Spice/Models/ViewModels/OrderListViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Spice.Models.ViewModels 7 | { 8 | public class OrderListViewModel 9 | { 10 | public IList Orders { get; set; } 11 | public PagingInfo PagingInfo { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Spice/Models/ViewModels/OrderDetailsViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Spice.Models.ViewModels 7 | { 8 | public class OrderDetailsViewModel 9 | { 10 | public OrderHeader OrderHeader { get; set; } 11 | public List OrderDetails { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/AccessDenied.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc.RazorPages; 6 | 7 | namespace Spice.Areas.Identity.Pages.Account 8 | { 9 | public class AccessDeniedModel : PageModel 10 | { 11 | public void OnGet() 12 | { 13 | 14 | } 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /Spice/Views/Shared/_StatusMessage.cshtml: -------------------------------------------------------------------------------- 1 | @model string 2 | 3 | @if (!String.IsNullOrEmpty(Model)) 4 | { 5 | var statusMessageClass = Model.StartsWith("Error") ? "danger" : "success"; 6 | 10 | } -------------------------------------------------------------------------------- /Spice/Models/ViewModels/MenuItemViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Spice.Models.ViewModels 7 | { 8 | public class MenuItemViewModel 9 | { 10 | public MenuItem MenuItem { get; set; } 11 | public IEnumerable Category { get; set; } 12 | public IEnumerable SubCategory { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Spice/Models/Category.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Spice.Models 8 | { 9 | public class Category 10 | { 11 | [Key] 12 | public int Id { get; set; } 13 | 14 | [Display(Name="Category Name")] 15 | [Required] 16 | public string Name { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Spice/Models/ViewModels/IndexViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Spice.Models.ViewModels 7 | { 8 | public class IndexViewModel 9 | { 10 | public IEnumerable MenuItem { get; set; } 11 | public IEnumerable Category { get; set; } 12 | public IEnumerable Coupon { get; set; } 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/_StatusMessage.cshtml: -------------------------------------------------------------------------------- 1 | @model string 2 | 3 | @if (!String.IsNullOrEmpty(Model)) 4 | { 5 | var statusMessageClass = Model.StartsWith("Error") ? "danger" : "success"; 6 | 10 | } -------------------------------------------------------------------------------- /Spice/Extensions/ReflectionExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Spice.Extensions 7 | { 8 | public static class ReflectionExtension 9 | { 10 | public static string GetPropertyValue(this T item, string propertyName) 11 | { 12 | return item.GetType().GetProperty(propertyName).GetValue(item, null).ToString(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using Microsoft.AspNetCore.Authorization; 5 | using Microsoft.AspNetCore.Mvc.RazorPages; 6 | 7 | namespace Spice.Areas.Identity.Pages.Account 8 | { 9 | [AllowAnonymous] 10 | public class ForgotPasswordConfirmation : PageModel 11 | { 12 | public void OnGet() 13 | { 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Lockout.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Authorization; 6 | using Microsoft.AspNetCore.Mvc.RazorPages; 7 | 8 | namespace Spice.Areas.Identity.Pages.Account 9 | { 10 | [AllowAnonymous] 11 | public class LockoutModel : PageModel 12 | { 13 | public void OnGet() 14 | { 15 | 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Authorization; 6 | using Microsoft.AspNetCore.Mvc.RazorPages; 7 | 8 | namespace Spice.Areas.Identity.Pages.Account 9 | { 10 | [AllowAnonymous] 11 | public class ResetPasswordConfirmationModel : PageModel 12 | { 13 | public void OnGet() 14 | { 15 | 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Spice/Models/ViewModels/SubCategoryAndCategoryViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Spice.Models.ViewModels 7 | { 8 | public class SubCategoryAndCategoryViewModel 9 | { 10 | public IEnumerable CategoryList { get; set; } 11 | public SubCategory SubCategory { get; set; } 12 | public List SubCategoryList { get; set; } 13 | public string StatusMessage { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Spice/Models/PagingInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Spice.Models 7 | { 8 | public class PagingInfo 9 | { 10 | public int TotalItem { get; set; } 11 | 12 | public int ItemsPerPage { get; set; } 13 | 14 | public int CurrentPage { get; set; } 15 | 16 | public int totalPage => (int)Math.Ceiling((decimal)TotalItem / ItemsPerPage); 17 | 18 | public string urlParam { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Spice/Models/ApplicationUser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Spice.Models 8 | { 9 | public class ApplicationUser : IdentityUser 10 | { 11 | public string Name { get; set; } 12 | public string StreetAddress { get; set; } 13 | public string City { get; set; } 14 | public string State { get; set; } 15 | public string PostalCode { get; set; } 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | 5 |

Manage your account

6 | 7 |
8 |

Change your account settings

9 |
10 |
11 |
12 | 13 |
14 |
15 | @RenderBody() 16 |
17 |
18 |
19 | 20 | @section Scripts { 21 | @RenderSection("Scripts", required: false) 22 | } 23 | -------------------------------------------------------------------------------- /Spice/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=Spice;Trusted_Connection=True;MultipleActiveResultSets=true" 4 | }, 5 | "Logging": { 6 | "LogLevel": { 7 | "Default": "Warning" 8 | } 9 | }, 10 | "AllowedHosts": "*", 11 | "Stripe": { 12 | "SecretKey": "sk_test_kGzUGDqcDrmVHhktqZZUFyI7", 13 | "PublishableKey": "pk_test_DS6jsf1BPuhpojL8FqWXbBpT" 14 | }, 15 | "SendGridKey": "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" 16 | } 17 | -------------------------------------------------------------------------------- /Spice/Views/Shared/_OrderStatus.cshtml: -------------------------------------------------------------------------------- 1 | @model string 2 | @using Spice.Utility 3 |
4 | @if (Model == SD.StatusSubmitted) 5 | { 6 | 7 | } 8 | @if (Model == SD.StatusInProcess) 9 | { 10 | 11 | } 12 | @if (Model == SD.StatusReady) 13 | { 14 | 15 | } 16 | @if (Model == SD.StatusCompleted) 17 | { 18 | 19 | } 20 |
-------------------------------------------------------------------------------- /Spice/Views/Shared/_TableButtonPartial.cshtml: -------------------------------------------------------------------------------- 1 | @model int 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | -------------------------------------------------------------------------------- /Spice/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) .NET Foundation. All rights reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 4 | these files except in compliance with the License. You may obtain a copy of the 5 | License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software distributed 10 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 11 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 12 | specific language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /Spice/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace Spice 12 | { 13 | public class Program 14 | { 15 | public static void Main(string[] args) 16 | { 17 | CreateWebHostBuilder(args).Build().Run(); 18 | } 19 | 20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 21 | WebHost.CreateDefaultBuilder(args) 22 | .UseStartup(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Error.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using Microsoft.AspNetCore.Authorization; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Microsoft.AspNetCore.Mvc.RazorPages; 5 | 6 | namespace Spice.Areas.Identity.Pages 7 | { 8 | [AllowAnonymous] 9 | [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] 10 | public class ErrorModel : PageModel 11 | { 12 | public string RequestId { get; set; } 13 | 14 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 15 | 16 | public void OnGet() 17 | { 18 | RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/IdentityHostingStartup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.AspNetCore.Identity; 4 | using Microsoft.AspNetCore.Identity.UI; 5 | using Microsoft.EntityFrameworkCore; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.DependencyInjection; 8 | using Spice.Data; 9 | 10 | [assembly: HostingStartup(typeof(Spice.Areas.Identity.IdentityHostingStartup))] 11 | namespace Spice.Areas.Identity 12 | { 13 | public class IdentityHostingStartup : IHostingStartup 14 | { 15 | public void Configure(IWebHostBuilder builder) 16 | { 17 | builder.ConfigureServices((context, services) => { 18 | }); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/Category/Details.cshtml: -------------------------------------------------------------------------------- 1 | @model Spice.Models.Category 2 | 3 | @{ 4 | ViewData["Title"] = "Details"; 5 | } 6 | 7 |
8 |

Category Details

9 |
10 |
11 |
12 |
13 | 14 |
15 |
16 | 17 |
18 |
19 | 20 |
21 |
22 | 23 |
24 |
25 | 26 |
27 | -------------------------------------------------------------------------------- /Spice/Models/SubCategory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace Spice.Models 9 | { 10 | public class SubCategory 11 | { 12 | [Key] 13 | public int Id { get; set; } 14 | 15 | [Display(Name = "SubCategory Name")] 16 | [Required] 17 | public string Name { get; set; } 18 | 19 | [Required] 20 | [Display(Name ="Category")] 21 | public int CategoryId { get; set; } 22 | 23 | [ForeignKey("CategoryId")] 24 | public virtual Category Category { get; set; } 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Spice/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:63625", 7 | "sslPort": 44347 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "Spice": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "applicationUrl": "https://localhost:5001;http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Spice/Extensions/IEnumerableExtension.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.Rendering; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Spice.Extensions 8 | { 9 | public static class IEnumerableExtension 10 | { 11 | public static IEnumerable ToSelectListItem(this IEnumerable items, int selectedValue) 12 | { 13 | return from item in items 14 | select new SelectListItem 15 | { 16 | Text = item.GetPropertyValue("Name"), 17 | Value = item.GetPropertyValue("Id"), 18 | Selected = item.GetPropertyValue("Id").Equals(selectedValue.ToString()) 19 | }; 20 | } 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Spice/Models/Coupon.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Spice.Models 8 | { 9 | public class Coupon 10 | { 11 | [Key] 12 | public int Id { get; set; } 13 | 14 | [Required] 15 | public string Name { get; set; } 16 | 17 | [Required] 18 | public string CouponType { get; set; } 19 | 20 | public enum ECouponType { Percent = 0, Dollar = 1 } 21 | 22 | [Required] 23 | public double Discount { get; set; } 24 | 25 | [Required] 26 | public double MinimumAmount { get; set; } 27 | 28 | public byte[] Picture { get; set; } 29 | 30 | [Display(Name="Is Active")] 31 | public bool IsActive { get; set; } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/ForgotPassword.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model ForgotPasswordModel 3 | @{ 4 | ViewData["Title"] = "Forgot your password?"; 5 | } 6 | 7 |

@ViewData["Title"]

8 |

Enter your email.

9 |
10 |
11 |
12 |
13 |
14 |
15 | 16 | 17 | 18 |
19 | 20 |
21 |
22 |
23 | 24 | @section Scripts { 25 | 26 | } 27 | -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/Category/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @model Spice.Models.Category 2 | 3 | @{ 4 | ViewData["Title"] = "Delete"; 5 | Layout = "~/Views/Shared/_Layout.cshtml"; 6 | } 7 |
8 |

Delete Category

9 |
10 | 11 |
12 |
13 |
14 |
15 | 16 |
17 |
18 | 19 |
20 |
21 |
22 |
23 | 24 |
25 |
26 |
27 |
-------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Error.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model ErrorModel 3 | @{ 4 | ViewData["Title"] = "Error"; 5 | } 6 | 7 |

Error.

8 |

An error occurred while processing your request.

9 | 10 | @if (Model.ShowRequestId) 11 | { 12 |

13 | Request ID: @Model.RequestId 14 |

15 | } 16 | 17 |

Development Mode

18 |

19 | Swapping to Development environment will display more detailed information about the error that occurred. 20 |

21 |

22 | Development environment should not be enabled in deployed applications, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the ASPNETCORE_ENVIRONMENT environment variable to Development, and restarting the application. 23 |

24 | -------------------------------------------------------------------------------- /Spice/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model ErrorViewModel 2 | @{ 3 | ViewData["Title"] = "Error"; 4 | } 5 | 6 |

Error.

7 |

An error occurred while processing your request.

8 | 9 | @if (Model.ShowRequestId) 10 | { 11 |

12 | Request ID: @Model.RequestId 13 |

14 | } 15 | 16 |

Development Mode

17 |

18 | Swapping to Development environment will display more detailed information about the error that occurred. 19 |

20 |

21 | The Development environment shouldn't be enabled for deployed applications. 22 | It can result in displaying sensitive information from exceptions to end users. 23 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 24 | and restarting the app. 25 |

26 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model Disable2faModel 3 | @{ 4 | ViewData["Title"] = "Disable two-factor authentication (2FA)"; 5 | ViewData["ActivePage"] = ManageNavPages.TwoFactorAuthentication; 6 | } 7 | 8 | 9 |

@ViewData["Title"]

10 | 11 | 21 | 22 |
23 |
24 | 25 |
26 |
27 | -------------------------------------------------------------------------------- /Spice/ScaffoldingReadMe.txt: -------------------------------------------------------------------------------- 1 | Support for ASP.NET Core Identity was added to your project 2 | - The code for adding Identity to your project was generated under Areas/Identity. 3 | 4 | Configuration of the Identity related services can be found in the Areas/Identity/IdentityHostingStartup.cs file. 5 | 6 | 7 | The generated UI requires support for static files. To add static files to your app: 8 | 1. Call app.UseStaticFiles() from your Configure method 9 | 10 | To use ASP.NET Core Identity you also need to enable authentication. To authentication to your app: 11 | 1. Call app.UseAuthentication() from your Configure method (after static files) 12 | 13 | The generated UI requires MVC. To add MVC to your app: 14 | 1. Call services.AddMvc() from your ConfigureServices method 15 | 2. Call app.UseMvc() from your Configure method (after authentication) 16 | 17 | Apps that use ASP.NET Core Identity should also use HTTPS. To enable HTTPS see https://go.microsoft.com/fwlink/?linkid=848054. 18 | 19 | -------------------------------------------------------------------------------- /Spice/Models/OrderDetails.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace Spice.Models 9 | { 10 | public class OrderDetails 11 | { 12 | [Key] 13 | public int Id { get; set; } 14 | 15 | [Required] 16 | public int OrderId { get; set; } 17 | 18 | [ForeignKey("OrderId")] 19 | public virtual OrderHeader OrderHeader { get; set; } 20 | 21 | [Required] 22 | public int MenuItemId { get; set; } 23 | 24 | [ForeignKey("MenuItemId")] 25 | public virtual MenuItem MenuItem { get; set; } 26 | 27 | public int Count { get; set; } 28 | 29 | public string Name { get; set; } 30 | public string Description { get; set; } 31 | 32 | [Required] 33 | public double Price { get; set; } 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Spice/Data/ApplicationDbContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore; 6 | using Spice.Models; 7 | 8 | namespace Spice.Data 9 | { 10 | public class ApplicationDbContext : IdentityDbContext 11 | { 12 | public ApplicationDbContext(DbContextOptions options) 13 | : base(options) 14 | { 15 | } 16 | 17 | public DbSet Category { get; set; } 18 | public DbSet SubCategory { get; set; } 19 | public DbSet MenuItem { get; set; } 20 | public DbSet Coupon { get; set; } 21 | public DbSet ApplicationUser { get; set; } 22 | public DbSet ShoppingCart { get; set; } 23 | public DbSet OrderHeader { get; set; } 24 | public DbSet OrderDetails { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Spice/ViewComponenets/UserNameViewComponent.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.EntityFrameworkCore; 3 | using Spice.Data; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Security.Claims; 8 | using System.Threading.Tasks; 9 | 10 | namespace Spice.ViewComponenets 11 | { 12 | public class UserNameViewComponent : ViewComponent 13 | { 14 | private readonly ApplicationDbContext _db; 15 | 16 | public UserNameViewComponent(ApplicationDbContext db) 17 | { 18 | _db = db; 19 | } 20 | 21 | public async Task InvokeAsync() 22 | { 23 | var claimsIdentity = (ClaimsIdentity)User.Identity; 24 | var claims = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier); 25 | 26 | var userFromDb = await _db.ApplicationUser.FirstOrDefaultAsync(u => u.Id == claims.Value); 27 | 28 | return View(userFromDb); 29 | } 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/PersonalData.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model PersonalDataModel 3 | @{ 4 | ViewData["Title"] = "Personal Data"; 5 | ViewData["ActivePage"] = ManageNavPages.PersonalData; 6 | } 7 | 8 |

@ViewData["Title"]

9 | 10 |
11 |
12 |

Your account contains personal data that you have given us. This page allows you to download or delete that data.

13 |

14 | Deleting this data will permanently remove your account, and this cannot be recovered. 15 |

16 |
17 | 18 |
19 |

20 | Delete 21 |

22 |
23 |
24 | 25 | @section Scripts { 26 | 27 | } -------------------------------------------------------------------------------- /Spice/Models/ShoppingCart.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace Spice.Models 9 | { 10 | public class ShoppingCart 11 | { 12 | public ShoppingCart() 13 | { 14 | Count = 1; 15 | } 16 | 17 | 18 | public int Id { get; set; } 19 | 20 | public string ApplicationUserId { get; set; } 21 | 22 | [NotMapped] 23 | [ForeignKey("ApplicationUserId")] 24 | public virtual ApplicationUser ApplicationUser { get; set; } 25 | 26 | public int MenuItemId { get; set; } 27 | 28 | [NotMapped] 29 | [ForeignKey("MenuItemId")] 30 | public virtual MenuItem MenuItem { get; set; } 31 | 32 | 33 | 34 | [Range(1,int.MaxValue, ErrorMessage ="Please enter a value greater than or equal to {1}")] 35 | public int Count { get; set; } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Spice/Views/Shared/_LoginPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Identity 2 | @inject SignInManager SignInManager 3 | @inject UserManager UserManager 4 | 5 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model ResetAuthenticatorModel 3 | @{ 4 | ViewData["Title"] = "Reset authenticator key"; 5 | ViewData["ActivePage"] = ManageNavPages.TwoFactorAuthentication; 6 | } 7 | 8 | 9 |

@ViewData["Title"]

10 | 20 |
21 |
22 | 23 |
24 |
-------------------------------------------------------------------------------- /Spice/Areas/Customer/Views/Order/Confirm.cshtml: -------------------------------------------------------------------------------- 1 | @model Spice.Models.ViewModels.OrderDetailsViewModel 2 | @{ 3 | ViewData["Title"] = "Confirm"; 4 | Layout = "~/Views/Shared/_Layout.cshtml"; 5 | } 6 | 7 |
8 |
9 |
10 |
11 |

Order Confirmed

12 |
13 |
14 | New Order 15 |
16 |
17 | 18 | @if(Model.OrderHeader !=null) 19 | { 20 |
21 | Your order has been confirmed! Please see the order summary below. 22 |
23 | Feel free to contact us if you have any questions. 24 |
25 | 26 | } 27 | else 28 | { 29 |
Error... Please try again.
30 | } 31 |
32 | 33 | -------------------------------------------------------------------------------- /Spice/Properties/PublishProfiles/FolderProfile.pubxml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | FileSystem 9 | FileSystem 10 | Release 11 | Any CPU 12 | 13 | True 14 | False 15 | c85632f6-a9e9-49cf-931e-cbbd79e05d20 16 | bin\Debug\netcoreapp2.2\publish\ 17 | False 18 | 19 | -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/SubCategory/Details.cshtml: -------------------------------------------------------------------------------- 1 | @model Spice.Models.SubCategory 2 | 3 |
4 |

Sub Category Details

5 |
6 |
7 |
8 |
9 |
10 | 11 |
12 |
13 | 14 |
15 |
16 |
17 |
18 | 19 |
20 |
21 | 22 |
23 |
24 |
25 |
26 |
27 |
28 | 29 |
30 |
31 |
32 | -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/Category/Create.cshtml: -------------------------------------------------------------------------------- 1 | @model Category 2 | @{ 3 | ViewData["Title"] = "Create"; 4 | Layout = "~/Views/Shared/_Layout.cshtml"; 5 | } 6 | 7 |
8 |

Create Category

9 |
10 | 11 |
12 |
13 |
14 |
15 |
16 | 17 |
18 |
19 | 20 |
21 | 22 |
23 |
24 |
25 | 26 |
27 |
28 |
29 |
30 | 31 | @section Scripts{ 32 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial");} 33 | } -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model LoginWithRecoveryCodeModel 3 | @{ 4 | ViewData["Title"] = "Recovery code verification"; 5 | } 6 | 7 |

@ViewData["Title"]

8 |
9 |

10 | You have requested to log in with a recovery code. This login will not be remembered until you provide 11 | an authenticator app code at log in or disable 2FA and log in again. 12 |

13 |
14 |
15 |
16 |
17 |
18 | 19 | 20 | 21 |
22 | 23 |
24 |
25 |
26 | 27 | @section Scripts { 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/PersonalData.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.AspNetCore.Identity; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Microsoft.AspNetCore.Mvc.RazorPages; 5 | using Microsoft.Extensions.Logging; 6 | 7 | namespace Spice.Areas.Identity.Pages.Account.Manage 8 | { 9 | public class PersonalDataModel : PageModel 10 | { 11 | private readonly UserManager _userManager; 12 | private readonly ILogger _logger; 13 | 14 | public PersonalDataModel( 15 | UserManager userManager, 16 | ILogger logger) 17 | { 18 | _userManager = userManager; 19 | _logger = logger; 20 | } 21 | 22 | public async Task OnGet() 23 | { 24 | var user = await _userManager.GetUserAsync(User); 25 | if (user == null) 26 | { 27 | return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); 28 | } 29 | 30 | return Page(); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/Category/Edit.cshtml: -------------------------------------------------------------------------------- 1 | @model Spice.Models.Category 2 | 3 | @{ 4 | ViewData["Title"] = "Edit"; 5 | Layout = "~/Views/Shared/_Layout.cshtml"; 6 | } 7 | 8 |
9 |

Edit Category

10 |
11 | 12 |
13 |
14 |
15 |
16 |
17 | 18 |
19 |
20 | 21 |
22 | 23 |
24 |
25 |
26 | 27 |
28 |
29 |
30 |
31 | 32 | 33 | @section Scripts{ 34 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial");} 35 | } -------------------------------------------------------------------------------- /Spice/Views/Shared/_CookieConsentPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Http.Features 2 | 3 | @{ 4 | var consentFeature = Context.Features.Get(); 5 | var showBanner = !consentFeature?.CanTrack ?? false; 6 | var cookieString = consentFeature?.CreateConsentCookie(); 7 | } 8 | 9 | @if (showBanner) 10 | { 11 | 17 | 25 | } 26 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model GenerateRecoveryCodesModel 3 | @{ 4 | ViewData["Title"] = "Generate two-factor authentication (2FA) recovery codes"; 5 | ViewData["ActivePage"] = ManageNavPages.TwoFactorAuthentication; 6 | } 7 | 8 | 9 |

@ViewData["Title"]

10 | 23 |
24 |
25 | 26 |
27 |
-------------------------------------------------------------------------------- /Spice/Data/Migrations/20181206183855_addCategoryToDatabase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Metadata; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | namespace Spice.Data.Migrations 5 | { 6 | public partial class addCategoryToDatabase : Migration 7 | { 8 | protected override void Up(MigrationBuilder migrationBuilder) 9 | { 10 | migrationBuilder.CreateTable( 11 | name: "Category", 12 | columns: table => new 13 | { 14 | Id = table.Column(nullable: false) 15 | .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 16 | Name = table.Column(nullable: false) 17 | }, 18 | constraints: table => 19 | { 20 | table.PrimaryKey("PK_Category", x => x.Id); 21 | }); 22 | } 23 | 24 | protected override void Down(MigrationBuilder migrationBuilder) 25 | { 26 | migrationBuilder.DropTable( 27 | name: "Category"); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Spice.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.136 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spice", "Spice\Spice.csproj", "{C85632F6-A9E9-49CF-931E-CBBD79E05D20}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {C85632F6-A9E9-49CF-931E-CBBD79E05D20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {C85632F6-A9E9-49CF-931E-CBBD79E05D20}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {C85632F6-A9E9-49CF-931E-CBBD79E05D20}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {C85632F6-A9E9-49CF-931E-CBBD79E05D20}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {86C90299-F498-4B2A-9F32-BBB6C85FAAD7} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/_ManageNav.cshtml: -------------------------------------------------------------------------------- 1 | @inject SignInManager SignInManager 2 | @{ 3 | var hasExternalLogins = (await SignInManager.GetExternalAuthenticationSchemesAsync()).Any(); 4 | } 5 | 15 | -------------------------------------------------------------------------------- /Spice/wwwroot/lib/jquery-validation/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright Jörn Zaefferer 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Spice/Views/Shared/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 18 | 19 | -------------------------------------------------------------------------------- /Spice/Models/MenuItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace Spice.Models 9 | { 10 | public class MenuItem 11 | { 12 | public int Id { get; set; } 13 | 14 | [Required] 15 | public string Name { get; set; } 16 | public string Description { get; set; } 17 | 18 | public string Spicyness { get; set; } 19 | public enum ESpicy { NA=0,NotSpicy=1, Spicy=2, VerySpicy=3} 20 | 21 | public string Image { get; set; } 22 | 23 | [Display(Name="Category")] 24 | public int CategoryId { get; set; } 25 | 26 | [ForeignKey("CategoryId")] 27 | public virtual Category Category { get; set; } 28 | 29 | [Display(Name = "SubCategory")] 30 | public int SubCategoryId { get; set; } 31 | 32 | [ForeignKey("SubCategoryId")] 33 | public virtual SubCategory SubCategory { get; set; } 34 | 35 | [Range(1,int.MaxValue, ErrorMessage =" Price should be greater than ${1}")] 36 | public double Price { get; set; } 37 | 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Spice/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2018 Twitter, Inc. 4 | Copyright (c) 2011-2018 The Bootstrap Authors 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/DeletePersonalData.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model DeletePersonalDataModel 3 | @{ 4 | ViewData["Title"] = "Delete Personal Data"; 5 | ViewData["ActivePage"] = ManageNavPages.PersonalData; 6 | } 7 | 8 |

@ViewData["Title"]

9 | 10 | 16 | 17 |
18 |
19 |
20 | @if (Model.RequirePassword) 21 | { 22 |
23 | 24 | 25 | 26 |
27 | } 28 | 29 |
30 |
31 | 32 | @section Scripts { 33 | 34 | } -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 18 | 19 | -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/SubCategory/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @model Spice.Models.SubCategory 2 | @{ 3 | ViewData["Title"] = "Delete"; 4 | } 5 |
6 |

Sub Category Delete

7 |
8 |
9 |
10 | 11 |
12 |
13 |
14 | 15 |
16 |
17 | 18 |
19 |
20 |
21 |
22 | 23 |
24 |
25 | 26 |
27 |
28 |
29 |
30 |
31 |
32 | 33 |
34 |
35 |
36 |
37 | 38 | -------------------------------------------------------------------------------- /Spice/Spice.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.0 5 | aspnet-Spice-C2B2C801-BDF3-487B-9131-1F7CDD5F9F28 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/Category/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | @{ 4 | ViewData["Title"] = "Index"; 5 | Layout = "~/Views/Shared/_Layout.cshtml"; 6 | } 7 | 8 |

9 |
10 |
11 |
12 |

Category List

13 |
14 |
15 | 16 |
17 |
18 |
19 |
20 | @if (Model.Count() > 0) 21 | { 22 | 23 | 24 | 27 | 28 | 29 | 30 | @foreach (var item in Model) 31 | { 32 | 33 | 36 | 39 | 40 | } 41 |
25 | @Html.DisplayNameFor(m => m.Name) 26 |
34 | @Html.DisplayFor(m => item.Name) 35 | 37 | 38 |
42 | } 43 | else 44 | { 45 |

No category exists...

46 | } 47 |
48 |
49 | 50 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model SetPasswordModel 3 | @{ 4 | ViewData["Title"] = "Set password"; 5 | ViewData["ActivePage"] = ManageNavPages.ChangePassword; 6 | } 7 | 8 |

Set your password

9 | 10 |

11 | You do not have a local username/password for this site. Add a local 12 | account so you can log in without an external login. 13 |

14 |
15 |
16 |
17 |
18 |
19 | 20 | 21 | 22 |
23 |
24 | 25 | 26 | 27 |
28 | 29 |
30 |
31 |
32 | 33 | @section Scripts { 34 | 35 | } -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Authorization; 6 | using Microsoft.AspNetCore.Identity; 7 | using Microsoft.AspNetCore.Mvc; 8 | using Microsoft.AspNetCore.Mvc.RazorPages; 9 | 10 | namespace Spice.Areas.Identity.Pages.Account 11 | { 12 | [AllowAnonymous] 13 | public class ConfirmEmailModel : PageModel 14 | { 15 | private readonly UserManager _userManager; 16 | 17 | public ConfirmEmailModel(UserManager userManager) 18 | { 19 | _userManager = userManager; 20 | } 21 | 22 | public async Task OnGetAsync(string userId, string code) 23 | { 24 | if (userId == null || code == null) 25 | { 26 | return RedirectToPage("/Index"); 27 | } 28 | 29 | var user = await _userManager.FindByIdAsync(userId); 30 | if (user == null) 31 | { 32 | return NotFound($"Unable to load user with ID '{userId}'."); 33 | } 34 | 35 | var result = await _userManager.ConfirmEmailAsync(user, code); 36 | if (!result.Succeeded) 37 | { 38 | throw new InvalidOperationException($"Error confirming email for user with ID '{userId}':"); 39 | } 40 | 41 | return Page(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Logout.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Authorization; 6 | using Microsoft.AspNetCore.Http; 7 | using Microsoft.AspNetCore.Identity; 8 | using Microsoft.AspNetCore.Mvc; 9 | using Microsoft.AspNetCore.Mvc.RazorPages; 10 | using Microsoft.Extensions.Logging; 11 | using Spice.Utility; 12 | 13 | namespace Spice.Areas.Identity.Pages.Account 14 | { 15 | [AllowAnonymous] 16 | public class LogoutModel : PageModel 17 | { 18 | private readonly SignInManager _signInManager; 19 | private readonly ILogger _logger; 20 | 21 | public LogoutModel(SignInManager signInManager, ILogger logger) 22 | { 23 | _signInManager = signInManager; 24 | _logger = logger; 25 | } 26 | 27 | public void OnGet() 28 | { 29 | } 30 | 31 | public async Task OnPost(string returnUrl = null) 32 | { 33 | await _signInManager.SignOutAsync(); 34 | HttpContext.Session.SetInt32(SD.ssShoppingCartCount, 0); 35 | _logger.LogInformation("User logged out."); 36 | if (returnUrl != null) 37 | { 38 | return LocalRedirect(returnUrl); 39 | } 40 | else 41 | { 42 | return RedirectToPage("Logout"); 43 | } 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/ResetPassword.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model ResetPasswordModel 3 | @{ 4 | ViewData["Title"] = "Reset password"; 5 | } 6 | 7 |

@ViewData["Title"]

8 |

Reset your password.

9 |
10 |
11 |
12 |
13 |
14 | 15 |
16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 |
25 |
26 | 27 | 28 | 29 |
30 | 31 |
32 |
33 |
34 | 35 | @section Scripts { 36 | 37 | } 38 | -------------------------------------------------------------------------------- /Spice/Data/Migrations/20181209071258_AddCouponToDatabase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Metadata; 3 | using Microsoft.EntityFrameworkCore.Migrations; 4 | 5 | namespace Spice.Data.Migrations 6 | { 7 | public partial class AddCouponToDatabase : Migration 8 | { 9 | protected override void Up(MigrationBuilder migrationBuilder) 10 | { 11 | migrationBuilder.CreateTable( 12 | name: "Coupon", 13 | columns: table => new 14 | { 15 | Id = table.Column(nullable: false) 16 | .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 17 | Name = table.Column(nullable: false), 18 | CouponType = table.Column(nullable: false), 19 | Discount = table.Column(nullable: false), 20 | MinimumAmount = table.Column(nullable: false), 21 | Picture = table.Column(nullable: true), 22 | IsActive = table.Column(nullable: false) 23 | }, 24 | constraints: table => 25 | { 26 | table.PrimaryKey("PK_Coupon", x => x.Id); 27 | }); 28 | } 29 | 30 | protected override void Down(MigrationBuilder migrationBuilder) 31 | { 32 | migrationBuilder.DropTable( 33 | name: "Coupon"); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Spice/Service/EmailSender.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity.UI.Services; 2 | using Microsoft.Extensions.Options; 3 | using SendGrid; 4 | using SendGrid.Helpers.Mail; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace Spice.Service 11 | { 12 | public class EmailSender : IEmailSender 13 | { 14 | public EmailOptions Options { get; set; } 15 | 16 | public EmailSender(IOptions emailOptions) 17 | { 18 | Options = emailOptions.Value; 19 | } 20 | 21 | public Task SendEmailAsync(string email, string subject, string message) 22 | { 23 | return Execute(Options.SendGridKey, subject, message, email); 24 | } 25 | 26 | private Task Execute(string sendGridKey, string subject, string message, string email) 27 | { 28 | var client = new SendGridClient(sendGridKey); 29 | var msg = new SendGridMessage() 30 | { 31 | From = new EmailAddress("admin@spice.com", "Spice Restaurant"), 32 | Subject = subject, 33 | PlainTextContent = message, 34 | HtmlContent = message 35 | }; 36 | msg.AddTo(new EmailAddress(email)); 37 | try 38 | { 39 | return client.SendEmailAsync(msg); 40 | } 41 | catch(Exception ex) 42 | { 43 | 44 | } 45 | return null; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model ChangePasswordModel 3 | @{ 4 | ViewData["Title"] = "Change password"; 5 | ViewData["ActivePage"] = ManageNavPages.ChangePassword; 6 | } 7 | 8 |

@ViewData["Title"]

9 | 10 |
11 |
12 |
13 |
14 |
15 | 16 | 17 | 18 |
19 |
20 | 21 | 22 | 23 |
24 |
25 | 26 | 27 | 28 |
29 | 30 |
31 |
32 |
33 | 34 | @section Scripts { 35 | 36 | } -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/ManageNavPages.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Mvc.Rendering; 3 | 4 | namespace Spice.Areas.Identity.Pages.Account.Manage 5 | { 6 | public static class ManageNavPages 7 | { 8 | public static string Index => "Index"; 9 | 10 | public static string ChangePassword => "ChangePassword"; 11 | 12 | public static string ExternalLogins => "ExternalLogins"; 13 | 14 | public static string PersonalData => "PersonalData"; 15 | 16 | public static string TwoFactorAuthentication => "TwoFactorAuthentication"; 17 | 18 | public static string IndexNavClass(ViewContext viewContext) => PageNavClass(viewContext, Index); 19 | 20 | public static string ChangePasswordNavClass(ViewContext viewContext) => PageNavClass(viewContext, ChangePassword); 21 | 22 | public static string ExternalLoginsNavClass(ViewContext viewContext) => PageNavClass(viewContext, ExternalLogins); 23 | 24 | public static string PersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, PersonalData); 25 | 26 | public static string TwoFactorAuthenticationNavClass(ViewContext viewContext) => PageNavClass(viewContext, TwoFactorAuthentication); 27 | 28 | private static string PageNavClass(ViewContext viewContext, string page) 29 | { 30 | var activePage = viewContext.ViewData["ActivePage"] as string 31 | ?? System.IO.Path.GetFileNameWithoutExtension(viewContext.ActionDescriptor.DisplayName); 32 | return string.Equals(activePage, page, StringComparison.OrdinalIgnoreCase) ? "active" : null; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/SubCategory/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | @{ 4 | ViewData["Title"] = "Index"; 5 | Layout = "~/Views/Shared/_Layout.cshtml"; 6 | } 7 | 8 |

9 |
10 |
11 |
12 |

Sub Category List

13 |
14 |
15 | 16 |
17 |
18 |
19 |
20 | @if (Model.Count() > 0) 21 | { 22 | 23 | 24 | 27 | 30 | 31 | 32 | 33 | @foreach (var item in Model) 34 | { 35 | 36 | 39 | 42 | 45 | 46 | } 47 |
25 | @Html.DisplayNameFor(m => m.Name) 26 | 28 | @Html.DisplayNameFor(m => m.Category.Name) 29 |
37 | @Html.DisplayFor(m => item.Name) 38 | 40 | @Html.DisplayFor(m => item.Category.Name) 41 | 43 | 44 |
48 | } 49 | else 50 | { 51 |

No Sub Category exists...

52 | } 53 |
54 |
55 | 56 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/LoginWith2fa.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model LoginWith2faModel 3 | @{ 4 | ViewData["Title"] = "Two-factor authentication"; 5 | } 6 | 7 |

@ViewData["Title"]

8 |
9 |

Your login is protected with an authenticator app. Enter your authenticator code below.

10 |
11 |
12 |
13 | 14 |
15 |
16 | 17 | 18 | 19 |
20 |
21 |
22 | 26 |
27 |
28 |
29 | 30 |
31 |
32 |
33 |
34 |

35 | Don't have access to your authenticator device? You can 36 | log in with a recovery code. 37 |

38 | 39 | @section Scripts { 40 | 41 | } 42 | -------------------------------------------------------------------------------- /Spice/Models/OrderHeader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace Spice.Models 9 | { 10 | public class OrderHeader 11 | { 12 | [Key] 13 | public int Id { get; set; } 14 | 15 | [Required] 16 | public string UserId { get; set; } 17 | 18 | [ForeignKey("UserId")] 19 | public virtual ApplicationUser ApplicationUser { get; set; } 20 | 21 | [Required] 22 | public DateTime OrderDate { get; set; } 23 | 24 | [Required] 25 | public double OrderTotalOriginal { get; set; } 26 | 27 | [Required] 28 | [DisplayFormat(DataFormatString = "{0:C}")] 29 | [Display(Name ="Order Total")] 30 | public double OrderTotal { get; set; } 31 | 32 | [Required] 33 | [Display(Name = "Pickup Time")] 34 | public DateTime PickUpTime { get; set; } 35 | 36 | [Required] 37 | [NotMapped] 38 | public DateTime PickUpDate { get; set; } 39 | 40 | [Display(Name ="Coupon Code")] 41 | public string CouponCode { get; set; } 42 | public double CouponCodeDiscount { get; set; } 43 | public string Status { get; set; } 44 | public string PaymentStatus { get; set; } 45 | public string Comments { get; set; } 46 | 47 | 48 | [Display(Name = "Pickup Name")] 49 | public string PickupName { get; set; } 50 | 51 | [Display(Name = "Phone Number")] 52 | public string PhoneNumber { get; set; } 53 | 54 | public string TransactionId { get; set; } 55 | 56 | 57 | 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Spice/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright JS Foundation and other contributors, https://js.foundation/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | All files located in the node_modules and external directories are 34 | externally maintained libraries used by this software which have their 35 | own licenses; we recommend you read them, as their terms may differ from 36 | the terms above. 37 | -------------------------------------------------------------------------------- /Spice/Data/Migrations/20181208181334_addSubCategoryToDatabase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Metadata; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | namespace Spice.Data.Migrations 5 | { 6 | public partial class addSubCategoryToDatabase : Migration 7 | { 8 | protected override void Up(MigrationBuilder migrationBuilder) 9 | { 10 | migrationBuilder.CreateTable( 11 | name: "SubCategory", 12 | columns: table => new 13 | { 14 | Id = table.Column(nullable: false) 15 | .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 16 | Name = table.Column(nullable: false), 17 | CategoryId = table.Column(nullable: false) 18 | }, 19 | constraints: table => 20 | { 21 | table.PrimaryKey("PK_SubCategory", x => x.Id); 22 | table.ForeignKey( 23 | name: "FK_SubCategory_Category_CategoryId", 24 | column: x => x.CategoryId, 25 | principalTable: "Category", 26 | principalColumn: "Id", 27 | onDelete: ReferentialAction.Cascade); 28 | }); 29 | 30 | migrationBuilder.CreateIndex( 31 | name: "IX_SubCategory_CategoryId", 32 | table: "SubCategory", 33 | column: "CategoryId"); 34 | } 35 | 36 | protected override void Down(MigrationBuilder migrationBuilder) 37 | { 38 | migrationBuilder.DropTable( 39 | name: "SubCategory"); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Spice/Properties/PublishProfiles/Spice20190104024839 - Web Deploy.pubxml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | MSDeploy 9 | /subscriptions/0156e113-a3a5-492a-b184-e0caa63d55d8/resourcegroups/Demo/providers/Microsoft.Web/sites/Spice20190104024839 10 | Demo 11 | AzureWebSite 12 | Release 13 | Any CPU 14 | https://spice20190104024839.azurewebsites.net 15 | True 16 | False 17 | c85632f6-a9e9-49cf-931e-cbbd79e05d20 18 | spice20190104024839.scm.azurewebsites.net:443 19 | Spice20190104024839 20 | 21 | True 22 | WMSVC 23 | True 24 | $Spice20190104024839 25 | <_SavePWD>True 26 | <_DestinationType>AzureWebSite 27 | netcoreapp2.2 28 | false 29 | <_IsPortable>true 30 | False 31 | 32 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/Index.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model IndexModel 3 | @{ 4 | ViewData["Title"] = "Profile"; 5 | ViewData["ActivePage"] = ManageNavPages.Index; 6 | } 7 | 8 |

@ViewData["Title"]

9 | 10 |
11 |
12 |
13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | @if (Model.IsEmailConfirmed) 21 | { 22 |
23 | 24 | 25 |
26 | } 27 | else 28 | { 29 | 30 | 31 | } 32 | 33 |
34 |
35 | 36 | 37 | 38 |
39 | 40 |
41 |
42 |
43 | 44 | @section Scripts { 45 | 46 | } -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/DownloadPersonalData.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Identity; 7 | using Microsoft.AspNetCore.Mvc; 8 | using Microsoft.AspNetCore.Mvc.RazorPages; 9 | using Microsoft.Extensions.Logging; 10 | using Newtonsoft.Json; 11 | 12 | namespace Spice.Areas.Identity.Pages.Account.Manage 13 | { 14 | public class DownloadPersonalDataModel : PageModel 15 | { 16 | private readonly UserManager _userManager; 17 | private readonly ILogger _logger; 18 | 19 | public DownloadPersonalDataModel( 20 | UserManager userManager, 21 | ILogger logger) 22 | { 23 | _userManager = userManager; 24 | _logger = logger; 25 | } 26 | 27 | public async Task OnPostAsync() 28 | { 29 | var user = await _userManager.GetUserAsync(User); 30 | if (user == null) 31 | { 32 | return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); 33 | } 34 | 35 | _logger.LogInformation("User with ID '{UserId}' asked for their personal data.", _userManager.GetUserId(User)); 36 | 37 | // Only include personal data for download 38 | var personalData = new Dictionary(); 39 | var personalDataProps = typeof(IdentityUser).GetProperties().Where( 40 | prop => Attribute.IsDefined(prop, typeof(PersonalDataAttribute))); 41 | foreach (var p in personalDataProps) 42 | { 43 | personalData.Add(p.Name, p.GetValue(user)?.ToString() ?? "null"); 44 | } 45 | 46 | Response.Headers.Add("Content-Disposition", "attachment; filename=PersonalData.json"); 47 | return new FileContentResult(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(personalData)), "text/json"); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Spice/TagHelpers/PageLinkTagHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.AspNetCore.Mvc.Rendering; 3 | using Microsoft.AspNetCore.Mvc.Routing; 4 | using Microsoft.AspNetCore.Mvc.ViewFeatures; 5 | using Microsoft.AspNetCore.Razor.TagHelpers; 6 | using Spice.Models; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Threading.Tasks; 11 | 12 | namespace Spice.TagHelpers 13 | { 14 | [HtmlTargetElement("div", Attributes ="page-model")] 15 | public class PageLinkTagHelper : TagHelper 16 | { 17 | private IUrlHelperFactory urlHelperFactory; 18 | 19 | public PageLinkTagHelper(IUrlHelperFactory helperFactory) 20 | { 21 | urlHelperFactory = helperFactory; 22 | } 23 | 24 | [ViewContext] 25 | [HtmlAttributeNotBound] 26 | public ViewContext ViewContext { get; set; } 27 | 28 | public PagingInfo PageModel { get; set; } 29 | public string PageAction { get; set; } 30 | public bool PageClassesEnabled { get; set; } 31 | public string PageClass { get; set; } 32 | public string PageClassNormal { get; set; } 33 | public string PageClassSelected { get; set; } 34 | 35 | public override void Process(TagHelperContext context, TagHelperOutput output) 36 | { 37 | IUrlHelper urlHelper = urlHelperFactory.GetUrlHelper(ViewContext); 38 | TagBuilder result = new TagBuilder("div"); 39 | 40 | for(int i=1;i<=PageModel.totalPage;i++) 41 | { 42 | TagBuilder tag = new TagBuilder("a"); 43 | string url = PageModel.urlParam.Replace(":", i.ToString()); 44 | tag.Attributes["href"] = url; 45 | if(PageClassesEnabled) 46 | { 47 | tag.AddCssClass(PageClass); 48 | tag.AddCssClass(i == PageModel.CurrentPage ? PageClassSelected : PageClassNormal); 49 | } 50 | tag.InnerHtml.Append(i.ToString()); 51 | result.InnerHtml.AppendHtml(tag); 52 | } 53 | 54 | output.Content.AppendHtml(result.InnerHtml); 55 | 56 | } 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/MenuItem/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | @{ 4 | ViewData["Title"] = "Index"; 5 | Layout = "~/Views/Shared/_Layout.cshtml"; 6 | } 7 | 8 |

9 |
10 |
11 |
12 |

Menu Item List

13 |
14 |
15 | 16 |
17 |
18 |
19 |
20 | @if (Model.Count() > 0) 21 | { 22 | 23 | 24 | 27 | 30 | 33 | 36 | 37 | 38 | 39 | @foreach (var item in Model) 40 | { 41 | 42 | 45 | 48 | 51 | 54 | 57 | 58 | } 59 |
25 | @Html.DisplayNameFor(m => m.Name) 26 | 28 | @Html.DisplayNameFor(m => m.Price) 29 | 31 | @Html.DisplayNameFor(m => m.CategoryId) 32 | 34 | @Html.DisplayNameFor(m => m.SubCategoryId) 35 |
43 | @Html.DisplayFor(m => item.Name) 44 | 46 | @Html.DisplayFor(m => item.Price) 47 | 49 | @Html.DisplayFor(m => item.Category.Name) 50 | 52 | @Html.DisplayFor(m => item.SubCategory.Name) 53 | 55 | 56 |
60 | } 61 | else 62 | { 63 |

No menu item exists...

64 | } 65 |
66 |
67 | 68 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model ExternalLoginsModel 3 | @{ 4 | ViewData["Title"] = "Manage your external logins"; 5 | ViewData["ActivePage"] = ManageNavPages.ExternalLogins; 6 | } 7 | 8 | 9 | @if (Model.CurrentLogins?.Count > 0) 10 | { 11 |

Registered Logins

12 | 13 | 14 | @foreach (var login in Model.CurrentLogins) 15 | { 16 | 17 | 18 | 34 | 35 | } 36 | 37 |
@login.ProviderDisplayName 19 | @if (Model.ShowRemoveButton) 20 | { 21 |
22 |
23 | 24 | 25 | 26 |
27 |
28 | } 29 | else 30 | { 31 | @:   32 | } 33 |
38 | } 39 | @if (Model.OtherLogins?.Count > 0) 40 | { 41 |

Add another service to log in.

42 |
43 | 53 | } -------------------------------------------------------------------------------- /Spice/Data/DbInitializer.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | using Microsoft.EntityFrameworkCore; 3 | using Spice.Models; 4 | using Spice.Utility; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace Spice.Data 11 | { 12 | public class DbInitializer : IDbInitializer 13 | { 14 | private readonly ApplicationDbContext _db; 15 | private readonly UserManager _userManager; 16 | private readonly RoleManager _roleManager; 17 | 18 | public DbInitializer(ApplicationDbContext db, UserManager userManager, RoleManager roleManager) 19 | { 20 | _db = db; 21 | _roleManager = roleManager; 22 | _userManager = userManager; 23 | } 24 | 25 | 26 | public async void Initialize() 27 | { 28 | try 29 | { 30 | if(_db.Database.GetPendingMigrations().Count()>0) 31 | { 32 | _db.Database.Migrate(); 33 | } 34 | } 35 | catch (Exception ex) 36 | { 37 | 38 | } 39 | 40 | if (_db.Roles.Any(r => r.Name == SD.ManagerUser)) return; 41 | 42 | _roleManager.CreateAsync(new IdentityRole(SD.ManagerUser)).GetAwaiter().GetResult(); 43 | _roleManager.CreateAsync(new IdentityRole(SD.FrontDeskUser)).GetAwaiter().GetResult(); 44 | _roleManager.CreateAsync(new IdentityRole(SD.KitchenUser)).GetAwaiter().GetResult(); 45 | _roleManager.CreateAsync(new IdentityRole(SD.CustomerEndUser)).GetAwaiter().GetResult(); 46 | 47 | _userManager.CreateAsync(new ApplicationUser 48 | { 49 | UserName = "admin@gmail.com", 50 | Email = "admin@gmail.com", 51 | Name = "Bhrugen Patel", 52 | EmailConfirmed = true, 53 | PhoneNumber = "1112223333" 54 | }, "Admin123*").GetAwaiter().GetResult(); 55 | 56 | IdentityUser user = await _db.Users.FirstOrDefaultAsync(u => u.Email == "admin@gmail.com"); 57 | 58 | await _userManager.AddToRoleAsync(user, SD.ManagerUser); 59 | 60 | } 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Spice/Areas/Admin/Controllers/UserController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Security.Claims; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Authorization; 7 | using Microsoft.AspNetCore.Mvc; 8 | using Microsoft.EntityFrameworkCore; 9 | using Spice.Data; 10 | using Spice.Utility; 11 | 12 | namespace Spice.Areas.Admin.Controllers 13 | { 14 | [Area("Admin")] 15 | [Authorize(Roles = SD.ManagerUser)] 16 | public class UserController : Controller 17 | { 18 | private readonly ApplicationDbContext _db; 19 | 20 | public UserController(ApplicationDbContext db) 21 | { 22 | _db = db; 23 | } 24 | 25 | public async Task Index() 26 | { 27 | var claimsIdentity = (ClaimsIdentity)this.User.Identity; 28 | var claim = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier); 29 | 30 | return View(await _db.ApplicationUser.Where(u=>u.Id != claim.Value).ToListAsync()); 31 | } 32 | 33 | 34 | public async Task Lock(string id) 35 | { 36 | if(id==null) 37 | { 38 | return NotFound(); 39 | } 40 | 41 | var applicationUser = await _db.ApplicationUser.FirstOrDefaultAsync(m => m.Id == id); 42 | 43 | if(applicationUser==null) 44 | { 45 | return NotFound(); 46 | } 47 | 48 | applicationUser.LockoutEnd = DateTime.Now.AddYears(1000); 49 | 50 | await _db.SaveChangesAsync(); 51 | 52 | return RedirectToAction(nameof(Index)); 53 | } 54 | 55 | public async Task UnLock(string id) 56 | { 57 | if (id == null) 58 | { 59 | return NotFound(); 60 | } 61 | 62 | var applicationUser = await _db.ApplicationUser.FirstOrDefaultAsync(m => m.Id == id); 63 | 64 | if (applicationUser == null) 65 | { 66 | return NotFound(); 67 | } 68 | 69 | applicationUser.LockoutEnd = DateTime.Now; 70 | 71 | await _db.SaveChangesAsync(); 72 | 73 | return RedirectToAction(nameof(Index)); 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /Spice/Data/Migrations/20181209210635_AddMoreFieldsToIdentityUser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | namespace Spice.Data.Migrations 4 | { 5 | public partial class AddMoreFieldsToIdentityUser : Migration 6 | { 7 | protected override void Up(MigrationBuilder migrationBuilder) 8 | { 9 | migrationBuilder.AddColumn( 10 | name: "Discriminator", 11 | table: "AspNetUsers", 12 | nullable: false, 13 | defaultValue: ""); 14 | 15 | migrationBuilder.AddColumn( 16 | name: "City", 17 | table: "AspNetUsers", 18 | nullable: true); 19 | 20 | migrationBuilder.AddColumn( 21 | name: "Name", 22 | table: "AspNetUsers", 23 | nullable: true); 24 | 25 | migrationBuilder.AddColumn( 26 | name: "PostalCode", 27 | table: "AspNetUsers", 28 | nullable: true); 29 | 30 | migrationBuilder.AddColumn( 31 | name: "State", 32 | table: "AspNetUsers", 33 | nullable: true); 34 | 35 | migrationBuilder.AddColumn( 36 | name: "StreetAddress", 37 | table: "AspNetUsers", 38 | nullable: true); 39 | } 40 | 41 | protected override void Down(MigrationBuilder migrationBuilder) 42 | { 43 | migrationBuilder.DropColumn( 44 | name: "Discriminator", 45 | table: "AspNetUsers"); 46 | 47 | migrationBuilder.DropColumn( 48 | name: "City", 49 | table: "AspNetUsers"); 50 | 51 | migrationBuilder.DropColumn( 52 | name: "Name", 53 | table: "AspNetUsers"); 54 | 55 | migrationBuilder.DropColumn( 56 | name: "PostalCode", 57 | table: "AspNetUsers"); 58 | 59 | migrationBuilder.DropColumn( 60 | name: "State", 61 | table: "AspNetUsers"); 62 | 63 | migrationBuilder.DropColumn( 64 | name: "StreetAddress", 65 | table: "AspNetUsers"); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model TwoFactorAuthenticationModel 3 | @{ 4 | ViewData["Title"] = "Two-factor authentication (2FA)"; 5 | ViewData["ActivePage"] = ManageNavPages.TwoFactorAuthentication; 6 | } 7 | 8 | 9 |

@ViewData["Title"]

10 | @if (Model.Is2faEnabled) 11 | { 12 | if (Model.RecoveryCodesLeft == 0) 13 | { 14 |
15 | You have no recovery codes left. 16 |

You must generate a new set of recovery codes before you can log in with a recovery code.

17 |
18 | } 19 | else if (Model.RecoveryCodesLeft == 1) 20 | { 21 |
22 | You have 1 recovery code left. 23 |

You can generate a new set of recovery codes.

24 |
25 | } 26 | else if (Model.RecoveryCodesLeft <= 3) 27 | { 28 |
29 | You have @Model.RecoveryCodesLeft recovery codes left. 30 |

You should generate a new set of recovery codes.

31 |
32 | } 33 | 34 | if (Model.IsMachineRemembered) 35 | { 36 |
37 | 38 |
39 | } 40 | Disable 2FA 41 | Reset recovery codes 42 | } 43 | 44 |
Authenticator app
45 | @if (!Model.HasAuthenticator) 46 | { 47 | Add authenticator app 48 | } 49 | else 50 | { 51 | Setup authenticator app 52 | Reset authenticator app 53 | } 54 | 55 | @section Scripts { 56 | 57 | } -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Identity; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.RazorPages; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace Spice.Areas.Identity.Pages.Account.Manage 11 | { 12 | public class ResetAuthenticatorModel : PageModel 13 | { 14 | UserManager _userManager; 15 | private readonly SignInManager _signInManager; 16 | ILogger _logger; 17 | 18 | public ResetAuthenticatorModel( 19 | UserManager userManager, 20 | SignInManager signInManager, 21 | ILogger logger) 22 | { 23 | _userManager = userManager; 24 | _signInManager = signInManager; 25 | _logger = logger; 26 | } 27 | 28 | [TempData] 29 | public string StatusMessage { get; set; } 30 | 31 | public async Task OnGet() 32 | { 33 | var user = await _userManager.GetUserAsync(User); 34 | if (user == null) 35 | { 36 | return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); 37 | } 38 | 39 | return Page(); 40 | } 41 | 42 | public async Task OnPostAsync() 43 | { 44 | var user = await _userManager.GetUserAsync(User); 45 | if (user == null) 46 | { 47 | return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); 48 | } 49 | 50 | await _userManager.SetTwoFactorEnabledAsync(user, false); 51 | await _userManager.ResetAuthenticatorKeyAsync(user); 52 | _logger.LogInformation("User with ID '{UserId}' has reset their authentication app key.", user.Id); 53 | 54 | await _signInManager.RefreshSignInAsync(user); 55 | StatusMessage = "Your authenticator app key has been reset, you will need to configure your authenticator app using the new key."; 56 | 57 | return RedirectToPage("./EnableAuthenticator"); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/Coupon/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | @{ 4 | ViewData["Title"] = "Index"; 5 | Layout = "~/Views/Shared/_Layout.cshtml"; 6 | } 7 | 8 |

9 |
10 |
11 |
12 |

Coupon List

13 |
14 |
15 | 16 |
17 |
18 |
19 |
20 | @if (Model.Count() > 0) 21 | { 22 | 23 | 24 | 27 | 30 | 33 | 36 | 37 | 38 | 39 | @foreach (var item in Model) 40 | { 41 | 42 | 45 | 48 | 51 | 54 | 57 | 58 | } 59 |
25 | @Html.DisplayNameFor(m => m.Name) 26 | 28 | @Html.DisplayNameFor(m => m.Discount) 29 | 31 | @Html.DisplayNameFor(m => m.MinimumAmount) 32 | 34 | @Html.DisplayNameFor(m => m.IsActive) 35 |
43 | @Html.DisplayFor(m => item.Name) 44 | 46 | @Html.DisplayFor(m => item.Discount) 47 | 49 | @Html.DisplayFor(m => item.MinimumAmount) 50 | 52 | @Html.DisplayFor(m => item.IsActive) 53 | 55 | 56 |
60 | } 61 | else 62 | { 63 |

No coupons exists...

64 | } 65 |
66 |
67 | 68 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Identity; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.RazorPages; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace Spice.Areas.Identity.Pages.Account.Manage 11 | { 12 | public class Disable2faModel : PageModel 13 | { 14 | private readonly UserManager _userManager; 15 | private readonly ILogger _logger; 16 | 17 | public Disable2faModel( 18 | UserManager userManager, 19 | ILogger logger) 20 | { 21 | _userManager = userManager; 22 | _logger = logger; 23 | } 24 | 25 | [TempData] 26 | public string StatusMessage { get; set; } 27 | 28 | public async Task OnGet() 29 | { 30 | var user = await _userManager.GetUserAsync(User); 31 | if (user == null) 32 | { 33 | return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); 34 | } 35 | 36 | if (!await _userManager.GetTwoFactorEnabledAsync(user)) 37 | { 38 | throw new InvalidOperationException($"Cannot disable 2FA for user with ID '{_userManager.GetUserId(User)}' as it's not currently enabled."); 39 | } 40 | 41 | return Page(); 42 | } 43 | 44 | public async Task OnPostAsync() 45 | { 46 | var user = await _userManager.GetUserAsync(User); 47 | if (user == null) 48 | { 49 | return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); 50 | } 51 | 52 | var disable2faResult = await _userManager.SetTwoFactorEnabledAsync(user, false); 53 | if (!disable2faResult.Succeeded) 54 | { 55 | throw new InvalidOperationException($"Unexpected error occurred disabling 2FA for user with ID '{_userManager.GetUserId(User)}'."); 56 | } 57 | 58 | _logger.LogInformation("User with ID '{UserId}' has disabled 2fa.", _userManager.GetUserId(User)); 59 | StatusMessage = "2fa has been disabled. You can reenable 2fa when you setup an authenticator app"; 60 | return RedirectToPage("./TwoFactorAuthentication"); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /Spice/Data/Migrations/20181209035249_AddMenuItemToDatabase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Metadata; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | namespace Spice.Data.Migrations 5 | { 6 | public partial class AddMenuItemToDatabase : Migration 7 | { 8 | protected override void Up(MigrationBuilder migrationBuilder) 9 | { 10 | migrationBuilder.CreateTable( 11 | name: "MenuItem", 12 | columns: table => new 13 | { 14 | Id = table.Column(nullable: false) 15 | .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 16 | Name = table.Column(nullable: false), 17 | Description = table.Column(nullable: true), 18 | Spicyness = table.Column(nullable: true), 19 | Image = table.Column(nullable: true), 20 | CategoryId = table.Column(nullable: false), 21 | SubCategoryId = table.Column(nullable: false), 22 | Price = table.Column(nullable: false) 23 | }, 24 | constraints: table => 25 | { 26 | table.PrimaryKey("PK_MenuItem", x => x.Id); 27 | table.ForeignKey( 28 | name: "FK_MenuItem_Category_CategoryId", 29 | column: x => x.CategoryId, 30 | principalTable: "Category", 31 | principalColumn: "Id", 32 | onDelete: ReferentialAction.NoAction); 33 | table.ForeignKey( 34 | name: "FK_MenuItem_SubCategory_SubCategoryId", 35 | column: x => x.SubCategoryId, 36 | principalTable: "SubCategory", 37 | principalColumn: "Id", 38 | onDelete: ReferentialAction.NoAction); 39 | }); 40 | 41 | migrationBuilder.CreateIndex( 42 | name: "IX_MenuItem_CategoryId", 43 | table: "MenuItem", 44 | column: "CategoryId"); 45 | 46 | migrationBuilder.CreateIndex( 47 | name: "IX_MenuItem_SubCategoryId", 48 | table: "MenuItem", 49 | column: "SubCategoryId"); 50 | } 51 | 52 | protected override void Down(MigrationBuilder migrationBuilder) 53 | { 54 | migrationBuilder.DropTable( 55 | name: "MenuItem"); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/ForgotPassword.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Text.Encodings.Web; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Authorization; 7 | using Microsoft.AspNetCore.Identity; 8 | using Microsoft.AspNetCore.Identity.UI.Services; 9 | using Microsoft.AspNetCore.Mvc; 10 | using Microsoft.AspNetCore.Mvc.RazorPages; 11 | 12 | namespace Spice.Areas.Identity.Pages.Account 13 | { 14 | [AllowAnonymous] 15 | public class ForgotPasswordModel : PageModel 16 | { 17 | private readonly UserManager _userManager; 18 | private readonly IEmailSender _emailSender; 19 | 20 | public ForgotPasswordModel(UserManager userManager, IEmailSender emailSender) 21 | { 22 | _userManager = userManager; 23 | _emailSender = emailSender; 24 | } 25 | 26 | [BindProperty] 27 | public InputModel Input { get; set; } 28 | 29 | public class InputModel 30 | { 31 | [Required] 32 | [EmailAddress] 33 | public string Email { get; set; } 34 | } 35 | 36 | public async Task OnPostAsync() 37 | { 38 | if (ModelState.IsValid) 39 | { 40 | var user = await _userManager.FindByEmailAsync(Input.Email); 41 | if (user == null || !(await _userManager.IsEmailConfirmedAsync(user))) 42 | { 43 | // Don't reveal that the user does not exist or is not confirmed 44 | return RedirectToPage("./ForgotPasswordConfirmation"); 45 | } 46 | 47 | // For more information on how to enable account confirmation and password reset please 48 | // visit https://go.microsoft.com/fwlink/?LinkID=532713 49 | var code = await _userManager.GeneratePasswordResetTokenAsync(user); 50 | var callbackUrl = Url.Page( 51 | "/Account/ResetPassword", 52 | pageHandler: null, 53 | values: new { code }, 54 | protocol: Request.Scheme); 55 | 56 | await _emailSender.SendEmailAsync( 57 | Input.Email, 58 | "Reset Password", 59 | $"Please reset your password by clicking here."); 60 | 61 | return RedirectToPage("./ForgotPasswordConfirmation"); 62 | } 63 | 64 | return Page(); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Spice/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | /* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | for details on configuring this project to bundle and minify static web assets. */ 3 | 4 | a.navbar-brand { 5 | white-space: normal; 6 | text-align: center; 7 | word-break: break-all; 8 | } 9 | 10 | /* Sticky footer styles 11 | -------------------------------------------------- */ 12 | html { 13 | font-size: 14px; 14 | } 15 | @media (min-width: 768px) { 16 | html { 17 | font-size: 16px; 18 | } 19 | } 20 | 21 | .border-top { 22 | border-top: 1px solid #e5e5e5; 23 | } 24 | .border-bottom { 25 | border-bottom: 1px solid #e5e5e5; 26 | } 27 | 28 | .box-shadow { 29 | box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05); 30 | } 31 | 32 | button.accept-policy { 33 | font-size: 1rem; 34 | line-height: inherit; 35 | } 36 | 37 | /* Sticky footer styles 38 | -------------------------------------------------- */ 39 | html { 40 | position: relative; 41 | min-height: 100%; 42 | } 43 | 44 | body { 45 | /* Margin bottom by footer height */ 46 | margin-bottom: 60px; 47 | } 48 | .footer { 49 | position: absolute; 50 | bottom: 0; 51 | width: 100%; 52 | white-space: nowrap; 53 | /* Set the fixed height of the footer here */ 54 | height: 60px; 55 | line-height: 60px; /* Vertically center the text there */ 56 | } 57 | 58 | 59 | 60 | .search-background{ 61 | background: url('/images/dust_scratches.png'); 62 | } 63 | 64 | .backgroundWhite{ 65 | background-color:white; 66 | padding:30px; 67 | border-radius:10px; 68 | margin-bottom:30px; 69 | } 70 | 71 | .backgroundWhiteBorder { 72 | background-color: white; 73 | padding: 30px; 74 | border-radius: 10px; 75 | margin-bottom: 30px; 76 | border:1px solid #ddd; 77 | } 78 | 79 | .backgroundWhiteBorder10Padding { 80 | background-color: white; 81 | padding: 10px; 82 | border-radius: 10px; 83 | border: 1px solid #ddd; 84 | } 85 | 86 | 87 | 88 | .menu-filter-list li{ 89 | display: inline-block; 90 | cursor:pointer; 91 | padding:10px 20px 10px; 92 | text-transform: uppercase; 93 | background: #f5f5f5; 94 | border-radius:5px; 95 | font-weight:700; 96 | font-size:13px; 97 | -moz-transition: all 0.3s; 98 | -o-transition: all 0.3s; 99 | -webkit-transition:all 0.3s; 100 | transition:all 0.3s; 101 | font-family:"Poppins",sans-serif; 102 | 103 | } 104 | 105 | .menu-filter-list li.is-checke, .menu-filter-list li:hover{ 106 | background-color:#545b62; 107 | color:#fff; 108 | } -------------------------------------------------------------------------------- /Spice/Views/Shared/_ThumbnailAreaPArtial.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | @* 3 | For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 4 | *@ 5 | 6 | @if (Model.Count() > 0) 7 | { 8 |
9 |
10 |

@Model.FirstOrDefault().Category.Name

11 |
12 | 13 | @foreach(var item in Model) 14 | { 15 |
16 |
17 |
18 | 19 |
20 |
21 |
22 |
23 | 24 | @if (item.Spicyness == "1") 25 | { 26 | 27 | } 28 | @if (item.Spicyness == "2") 29 | { 30 | 31 | } 32 | @if (item.Spicyness == "3") 33 | { 34 | 35 | } 36 |
37 |
38 |

$@item.Price

39 |
40 |
41 | 42 | 43 |
44 |

@Html.Raw(item.Description)

45 |
46 |
47 | Details 48 |
49 |
50 |
51 |
52 | } 53 |
54 |
55 | } -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/User/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | @{ 4 | ViewData["Title"] = "Index"; 5 | Layout = "~/Views/Shared/_Layout.cshtml"; 6 | } 7 | 8 |

9 |
10 |
11 |
12 |

Users List

13 |
14 | 17 |
18 |
19 |
20 | @if (Model.Count() > 0) 21 | { 22 | 23 | 24 | 27 | 30 | 33 | 34 | 35 | 36 | @foreach (var item in Model) 37 | { 38 | 39 | 42 | 45 | 48 | 63 | 64 | } 65 |
25 | @Html.DisplayNameFor(m => m.Name) 26 | 28 | @Html.DisplayNameFor(m => m.Email) 29 | 31 | @Html.DisplayNameFor(m => m.PhoneNumber) 32 |
40 | @Html.DisplayFor(m => item.Name) 41 | 43 | @Html.DisplayFor(m => item.Email) 44 | 46 | @Html.DisplayFor(m => item.PhoneNumber) 47 | 49 | 50 | @if (item.LockoutEnd == null || item.LockoutEnd < DateTime.Now) 51 | { 52 | 53 | 54 | 55 | } 56 | else 57 | { 58 | 59 | 60 | 61 | } 62 |
66 | } 67 | else 68 | { 69 |

No category exists...

70 | } 71 |
72 |
73 | 74 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/Coupon/Details.cshtml: -------------------------------------------------------------------------------- 1 | @model Spice.Models.Coupon 2 | @{ 3 | ViewData["Title"] = "Delete"; 4 | } 5 | 6 |
7 |

Coupon Details

8 |
9 |
10 |
11 |
12 | @{ 13 | var base64 = Convert.ToBase64String(Model.Picture); 14 | var imgsrc = string.Format("data:image/jpg;base64,{0}", base64); 15 | } 16 | 17 |
18 |
19 |
20 |
21 |
22 | 23 |
24 |
25 | 26 |
27 |
28 | 29 |
30 |
31 | 32 |
33 |
34 | 35 |
36 |
37 |
38 |
39 | 40 |
41 |
42 | 43 |
44 |
45 |
46 |
47 | 48 |
49 |
50 | 51 |
52 |
53 |
54 |
55 | 56 |
57 |
58 | 59 |
60 |
61 | 62 |
63 |
64 |
65 |
66 | 67 |
68 |
69 |
70 | 71 |
72 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Identity; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.RazorPages; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace Spice.Areas.Identity.Pages.Account.Manage 11 | { 12 | public class TwoFactorAuthenticationModel : PageModel 13 | { 14 | private const string AuthenicatorUriFormat = "otpauth://totp/{0}:{1}?secret={2}&issuer={0}"; 15 | 16 | private readonly UserManager _userManager; 17 | private readonly SignInManager _signInManager; 18 | private readonly ILogger _logger; 19 | 20 | public TwoFactorAuthenticationModel( 21 | UserManager userManager, 22 | SignInManager signInManager, 23 | ILogger logger) 24 | { 25 | _userManager = userManager; 26 | _signInManager = signInManager; 27 | _logger = logger; 28 | } 29 | 30 | public bool HasAuthenticator { get; set; } 31 | 32 | public int RecoveryCodesLeft { get; set; } 33 | 34 | [BindProperty] 35 | public bool Is2faEnabled { get; set; } 36 | 37 | public bool IsMachineRemembered { get; set; } 38 | 39 | [TempData] 40 | public string StatusMessage { get; set; } 41 | 42 | public async Task OnGet() 43 | { 44 | var user = await _userManager.GetUserAsync(User); 45 | if (user == null) 46 | { 47 | return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); 48 | } 49 | 50 | HasAuthenticator = await _userManager.GetAuthenticatorKeyAsync(user) != null; 51 | Is2faEnabled = await _userManager.GetTwoFactorEnabledAsync(user); 52 | IsMachineRemembered = await _signInManager.IsTwoFactorClientRememberedAsync(user); 53 | RecoveryCodesLeft = await _userManager.CountRecoveryCodesAsync(user); 54 | 55 | return Page(); 56 | } 57 | 58 | public async Task OnPost() 59 | { 60 | var user = await _userManager.GetUserAsync(User); 61 | if (user == null) 62 | { 63 | return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); 64 | } 65 | 66 | await _signInManager.ForgetTwoFactorClientAsync(); 67 | StatusMessage = "The current browser has been forgotten. When you login again from this browser you will be prompted for your 2fa code."; 68 | return RedirectToPage(); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Identity; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.RazorPages; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace Spice.Areas.Identity.Pages.Account.Manage 11 | { 12 | public class GenerateRecoveryCodesModel : PageModel 13 | { 14 | private readonly UserManager _userManager; 15 | private readonly ILogger _logger; 16 | 17 | public GenerateRecoveryCodesModel( 18 | UserManager userManager, 19 | ILogger logger) 20 | { 21 | _userManager = userManager; 22 | _logger = logger; 23 | } 24 | 25 | [TempData] 26 | public string[] RecoveryCodes { get; set; } 27 | 28 | [TempData] 29 | public string StatusMessage { get; set; } 30 | 31 | public async Task OnGetAsync() 32 | { 33 | var user = await _userManager.GetUserAsync(User); 34 | if (user == null) 35 | { 36 | return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); 37 | } 38 | 39 | var isTwoFactorEnabled = await _userManager.GetTwoFactorEnabledAsync(user); 40 | if (!isTwoFactorEnabled) 41 | { 42 | var userId = await _userManager.GetUserIdAsync(user); 43 | throw new InvalidOperationException($"Cannot generate recovery codes for user with ID '{userId}' because they do not have 2FA enabled."); 44 | } 45 | 46 | return Page(); 47 | } 48 | 49 | public async Task OnPostAsync() 50 | { 51 | var user = await _userManager.GetUserAsync(User); 52 | if (user == null) 53 | { 54 | return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); 55 | } 56 | 57 | var isTwoFactorEnabled = await _userManager.GetTwoFactorEnabledAsync(user); 58 | var userId = await _userManager.GetUserIdAsync(user); 59 | if (!isTwoFactorEnabled) 60 | { 61 | throw new InvalidOperationException($"Cannot generate recovery codes for user with ID '{userId}' as they do not have 2FA enabled."); 62 | } 63 | 64 | var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10); 65 | RecoveryCodes = recoveryCodes.ToArray(); 66 | 67 | _logger.LogInformation("User with ID '{UserId}' has generated new 2FA recovery codes.", userId); 68 | StatusMessage = "You have generated new recovery codes."; 69 | return RedirectToPage("./ShowRecoveryCodes"); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/ResetPassword.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Authorization; 7 | using Microsoft.AspNetCore.Identity; 8 | using Microsoft.AspNetCore.Mvc; 9 | using Microsoft.AspNetCore.Mvc.RazorPages; 10 | 11 | namespace Spice.Areas.Identity.Pages.Account 12 | { 13 | [AllowAnonymous] 14 | public class ResetPasswordModel : PageModel 15 | { 16 | private readonly UserManager _userManager; 17 | 18 | public ResetPasswordModel(UserManager userManager) 19 | { 20 | _userManager = userManager; 21 | } 22 | 23 | [BindProperty] 24 | public InputModel Input { get; set; } 25 | 26 | public class InputModel 27 | { 28 | [Required] 29 | [EmailAddress] 30 | public string Email { get; set; } 31 | 32 | [Required] 33 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] 34 | [DataType(DataType.Password)] 35 | public string Password { get; set; } 36 | 37 | [DataType(DataType.Password)] 38 | [Display(Name = "Confirm password")] 39 | [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] 40 | public string ConfirmPassword { get; set; } 41 | 42 | public string Code { get; set; } 43 | } 44 | 45 | public IActionResult OnGet(string code = null) 46 | { 47 | if (code == null) 48 | { 49 | return BadRequest("A code must be supplied for password reset."); 50 | } 51 | else 52 | { 53 | Input = new InputModel 54 | { 55 | Code = code 56 | }; 57 | return Page(); 58 | } 59 | } 60 | 61 | public async Task OnPostAsync() 62 | { 63 | if (!ModelState.IsValid) 64 | { 65 | return Page(); 66 | } 67 | 68 | var user = await _userManager.FindByEmailAsync(Input.Email); 69 | if (user == null) 70 | { 71 | // Don't reveal that the user does not exist 72 | return RedirectToPage("./ResetPasswordConfirmation"); 73 | } 74 | 75 | var result = await _userManager.ResetPasswordAsync(user, Input.Code, Input.Password); 76 | if (result.Succeeded) 77 | { 78 | return RedirectToPage("./ResetPasswordConfirmation"); 79 | } 80 | 81 | foreach (var error in result.Errors) 82 | { 83 | ModelState.AddModelError(string.Empty, error.Description); 84 | } 85 | return Page(); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/Coupon/Create.cshtml: -------------------------------------------------------------------------------- 1 | @model Spice.Models.Coupon 2 | @{ 3 | ViewData["Title"] = "Create"; 4 | Layout = "~/Views/Shared/_Layout.cshtml"; 5 | } 6 | 7 |
8 |

Create Coupon

9 |
10 | 11 |
12 |
13 |
14 |
15 |
16 | 17 |
18 |
19 | 20 |
21 | 22 |
23 |
24 |
25 | 26 |
27 |
28 | 29 |
30 |
31 |
32 |
33 | 34 |
35 |
36 | 37 |
38 |
39 |
40 |
41 | 42 |
43 |
44 | 45 |
46 | 47 |
48 |
49 |
50 | 51 |
52 |
53 | 54 |
55 | 56 |
57 |
58 |
59 | 60 |
61 |
62 | 63 |
64 |
65 |
66 |
67 | 68 |
69 |
70 |
71 |
72 | 73 | @section Scripts{ 74 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial");} 75 | } -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/Coupon/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @model Spice.Models.Coupon 2 | @{ 3 | ViewData["Title"] = "Delete"; 4 | } 5 | 6 |
7 |

Delete Coupon

8 |
9 |
10 |
11 |
12 |
13 | @{ 14 | var base64 = Convert.ToBase64String(Model.Picture); 15 | var imgsrc = string.Format("data:image/jpg;base64,{0}", base64); 16 | } 17 | 18 |
19 |
20 |
21 |
22 |
23 | 24 |
25 |
26 | 27 |
28 |
29 | 30 |
31 |
32 | 33 |
34 |
35 | 36 |
37 |
38 |
39 |
40 | 41 |
42 |
43 | 44 |
45 |
46 |
47 |
48 | 49 |
50 |
51 | 52 |
53 |
54 |
55 |
56 | 57 |
58 |
59 | 60 |
61 |
62 | 63 |
64 |
65 |
66 |
67 | 68 |
69 |
70 |
71 | 72 |
73 |
-------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/DeletePersonalData.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.Threading.Tasks; 4 | using Microsoft.AspNetCore.Identity; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.AspNetCore.Mvc.RazorPages; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace Spice.Areas.Identity.Pages.Account.Manage 10 | { 11 | public class DeletePersonalDataModel : PageModel 12 | { 13 | private readonly UserManager _userManager; 14 | private readonly SignInManager _signInManager; 15 | private readonly ILogger _logger; 16 | 17 | public DeletePersonalDataModel( 18 | UserManager userManager, 19 | SignInManager signInManager, 20 | ILogger logger) 21 | { 22 | _userManager = userManager; 23 | _signInManager = signInManager; 24 | _logger = logger; 25 | } 26 | 27 | [BindProperty] 28 | public InputModel Input { get; set; } 29 | 30 | public class InputModel 31 | { 32 | [Required] 33 | [DataType(DataType.Password)] 34 | public string Password { get; set; } 35 | } 36 | 37 | public bool RequirePassword { get; set; } 38 | 39 | public async Task OnGet() 40 | { 41 | var user = await _userManager.GetUserAsync(User); 42 | if (user == null) 43 | { 44 | return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); 45 | } 46 | 47 | RequirePassword = await _userManager.HasPasswordAsync(user); 48 | return Page(); 49 | } 50 | 51 | public async Task OnPostAsync() 52 | { 53 | var user = await _userManager.GetUserAsync(User); 54 | if (user == null) 55 | { 56 | return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); 57 | } 58 | 59 | RequirePassword = await _userManager.HasPasswordAsync(user); 60 | if (RequirePassword) 61 | { 62 | if (!await _userManager.CheckPasswordAsync(user, Input.Password)) 63 | { 64 | ModelState.AddModelError(string.Empty, "Password not correct."); 65 | return Page(); 66 | } 67 | } 68 | 69 | var result = await _userManager.DeleteAsync(user); 70 | var userId = await _userManager.GetUserIdAsync(user); 71 | if (!result.Succeeded) 72 | { 73 | throw new InvalidOperationException($"Unexpected error occurred deleteing user with ID '{userId}'."); 74 | } 75 | 76 | await _signInManager.SignOutAsync(); 77 | 78 | _logger.LogInformation("User with ID '{UserId}' deleted themselves.", userId); 79 | 80 | return Redirect("~/"); 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /Spice/Areas/Customer/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model Spice.Models.ViewModels.IndexViewModel 2 | 3 |
4 | 5 | @if (Model.Coupon.ToList().Count > 0) 6 | { 7 |
8 | 37 |
38 | 39 | } 40 | 41 |

42 | 43 |
44 | 45 | 53 | 54 | 55 | @foreach(var category in Model.Category) 56 | { 57 | 60 | } 61 |
62 | 63 | 64 | @section Scripts{ 65 | 68 | 69 | 93 | } -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model EnableAuthenticatorModel 3 | @{ 4 | ViewData["Title"] = "Configure authenticator app"; 5 | ViewData["ActivePage"] = ManageNavPages.TwoFactorAuthentication; 6 | } 7 | 8 | 9 |

@ViewData["Title"]

10 |
11 |

To use an authenticator app go through the following steps:

12 |
    13 |
  1. 14 |

    15 | Download a two-factor authenticator app like Microsoft Authenticator for 16 | Windows Phone, 17 | Android and 18 | iOS or 19 | Google Authenticator for 20 | Android and 21 | iOS. 22 |

    23 |
  2. 24 |
  3. 25 |

    Scan the QR Code or enter this key @Model.SharedKey into your two factor authenticator app. Spaces and casing do not matter.

    26 |
    To enable QR code generation please read our documentation.
    27 |
    28 |
    29 |
  4. 30 |
  5. 31 |

    32 | Once you have scanned the QR code or input the key above, your two factor authentication app will provide you 33 | with a unique code. Enter the code in the confirmation box below. 34 |

    35 |
    36 |
    37 |
    38 |
    39 | 40 | 41 | 42 |
    43 | 44 |
    45 |
    46 |
    47 |
    48 |
  6. 49 |
50 |
51 | 52 | @section Scripts { 53 | 54 | 55 | 58 | 59 | 66 | 67 | } -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Identity; 7 | using Microsoft.AspNetCore.Mvc; 8 | using Microsoft.AspNetCore.Mvc.RazorPages; 9 | 10 | namespace Spice.Areas.Identity.Pages.Account.Manage 11 | { 12 | public class SetPasswordModel : PageModel 13 | { 14 | private readonly UserManager _userManager; 15 | private readonly SignInManager _signInManager; 16 | 17 | public SetPasswordModel( 18 | UserManager userManager, 19 | SignInManager signInManager) 20 | { 21 | _userManager = userManager; 22 | _signInManager = signInManager; 23 | } 24 | 25 | [BindProperty] 26 | public InputModel Input { get; set; } 27 | 28 | [TempData] 29 | public string StatusMessage { get; set; } 30 | 31 | public class InputModel 32 | { 33 | [Required] 34 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] 35 | [DataType(DataType.Password)] 36 | [Display(Name = "New password")] 37 | public string NewPassword { get; set; } 38 | 39 | [DataType(DataType.Password)] 40 | [Display(Name = "Confirm new password")] 41 | [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] 42 | public string ConfirmPassword { get; set; } 43 | } 44 | 45 | public async Task OnGetAsync() 46 | { 47 | var user = await _userManager.GetUserAsync(User); 48 | if (user == null) 49 | { 50 | return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); 51 | } 52 | 53 | var hasPassword = await _userManager.HasPasswordAsync(user); 54 | 55 | if (hasPassword) 56 | { 57 | return RedirectToPage("./ChangePassword"); 58 | } 59 | 60 | return Page(); 61 | } 62 | 63 | public async Task OnPostAsync() 64 | { 65 | if (!ModelState.IsValid) 66 | { 67 | return Page(); 68 | } 69 | 70 | var user = await _userManager.GetUserAsync(User); 71 | if (user == null) 72 | { 73 | return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); 74 | } 75 | 76 | var addPasswordResult = await _userManager.AddPasswordAsync(user, Input.NewPassword); 77 | if (!addPasswordResult.Succeeded) 78 | { 79 | foreach (var error in addPasswordResult.Errors) 80 | { 81 | ModelState.AddModelError(string.Empty, error.Description); 82 | } 83 | return Page(); 84 | } 85 | 86 | await _signInManager.RefreshSignInAsync(user); 87 | StatusMessage = "Your password has been set."; 88 | 89 | return RedirectToPage(); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/SubCategory/Create.cshtml: -------------------------------------------------------------------------------- 1 | @model Spice.Models.ViewModels.SubCategoryAndCategoryViewModel 2 | @using Spice.Extensions 3 | 4 | @{ 5 | ViewData["Title"] = "Create"; 6 | Layout = "~/Views/Shared/_Layout.cshtml"; 7 | } 8 | 9 |
10 |

Create Sub Category

11 |
12 | 13 | 14 | 15 |
16 |
17 |
18 |
19 |
20 |
21 | 22 |
23 |
24 | 25 |
26 |
27 |
28 |
29 | 30 |
31 |
32 | 33 |
34 | 35 |
36 |
37 |
38 | 39 |
40 |
41 |
42 |
43 |
44 | @if(Model.SubCategoryList.Count() > 0) 45 | { 46 |

Existing Subcategories:

47 | 48 |
49 |
    50 |
    51 | } 52 |
    53 | 54 | 55 | 56 |
    57 | 58 | @section Scripts{ 59 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial");} 60 | 61 | 96 | 97 | 98 | } -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Authorization; 7 | using Microsoft.AspNetCore.Identity; 8 | using Microsoft.AspNetCore.Mvc; 9 | using Microsoft.AspNetCore.Mvc.RazorPages; 10 | using Microsoft.Extensions.Logging; 11 | 12 | namespace Spice.Areas.Identity.Pages.Account 13 | { 14 | [AllowAnonymous] 15 | public class LoginWithRecoveryCodeModel : PageModel 16 | { 17 | private readonly SignInManager _signInManager; 18 | private readonly ILogger _logger; 19 | 20 | public LoginWithRecoveryCodeModel(SignInManager signInManager, ILogger logger) 21 | { 22 | _signInManager = signInManager; 23 | _logger = logger; 24 | } 25 | 26 | [BindProperty] 27 | public InputModel Input { get; set; } 28 | 29 | public string ReturnUrl { get; set; } 30 | 31 | public class InputModel 32 | { 33 | [BindProperty] 34 | [Required] 35 | [DataType(DataType.Text)] 36 | [Display(Name = "Recovery Code")] 37 | public string RecoveryCode { get; set; } 38 | } 39 | 40 | public async Task OnGetAsync(string returnUrl = null) 41 | { 42 | // Ensure the user has gone through the username & password screen first 43 | var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); 44 | if (user == null) 45 | { 46 | throw new InvalidOperationException($"Unable to load two-factor authentication user."); 47 | } 48 | 49 | ReturnUrl = returnUrl; 50 | 51 | return Page(); 52 | } 53 | 54 | public async Task OnPostAsync(string returnUrl = null) 55 | { 56 | if (!ModelState.IsValid) 57 | { 58 | return Page(); 59 | } 60 | 61 | var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); 62 | if (user == null) 63 | { 64 | throw new InvalidOperationException($"Unable to load two-factor authentication user."); 65 | } 66 | 67 | var recoveryCode = Input.RecoveryCode.Replace(" ", string.Empty); 68 | 69 | var result = await _signInManager.TwoFactorRecoveryCodeSignInAsync(recoveryCode); 70 | 71 | if (result.Succeeded) 72 | { 73 | _logger.LogInformation("User with ID '{UserId}' logged in with a recovery code.", user.Id); 74 | return LocalRedirect(returnUrl ?? Url.Content("~/")); 75 | } 76 | if (result.IsLockedOut) 77 | { 78 | _logger.LogWarning("User with ID '{UserId}' account locked out.", user.Id); 79 | return RedirectToPage("./Lockout"); 80 | } 81 | else 82 | { 83 | _logger.LogWarning("Invalid recovery code entered for user with ID '{UserId}' ", user.Id); 84 | ModelState.AddModelError(string.Empty, "Invalid recovery code entered."); 85 | return Page(); 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/SubCategory/Edit.cshtml: -------------------------------------------------------------------------------- 1 | @model Spice.Models.ViewModels.SubCategoryAndCategoryViewModel 2 | @using Spice.Extensions 3 | 4 | @{ 5 | ViewData["Title"] = "Edit"; 6 | Layout = "~/Views/Shared/_Layout.cshtml"; 7 | } 8 | 9 |
    10 |

    Edit Sub Category

    11 |
    12 | 13 | 14 | 15 |
    16 |
    17 |
    18 | 19 | 20 |
    21 |
    22 |
    23 | 24 |
    25 |
    26 | 27 |
    28 |
    29 |
    30 |
    31 | 32 |
    33 |
    34 | 35 |
    36 | 37 |
    38 |
    39 |
    40 | 41 |
    42 |
    43 |
    44 |
    45 |
    46 | @if (Model.SubCategoryList.Count() > 0) 47 | { 48 |

    Existing Subcategories:

    49 | 50 |
    51 |
      52 |
      53 | } 54 |
      55 | 56 | 57 | 58 |
      59 | 60 | @section Scripts{ 61 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial");} 62 | 63 | 93 | 94 | 95 | } -------------------------------------------------------------------------------- /Spice/Data/Migrations/20181212202216_AddShoppingCartToDb.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Metadata; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | namespace Spice.Data.Migrations 5 | { 6 | public partial class AddShoppingCartToDb : Migration 7 | { 8 | protected override void Up(MigrationBuilder migrationBuilder) 9 | { 10 | migrationBuilder.AlterColumn( 11 | name: "Name", 12 | table: "AspNetUserTokens", 13 | nullable: false, 14 | oldClrType: typeof(string), 15 | oldMaxLength: 128); 16 | 17 | migrationBuilder.AlterColumn( 18 | name: "LoginProvider", 19 | table: "AspNetUserTokens", 20 | nullable: false, 21 | oldClrType: typeof(string), 22 | oldMaxLength: 128); 23 | 24 | migrationBuilder.AlterColumn( 25 | name: "ProviderKey", 26 | table: "AspNetUserLogins", 27 | nullable: false, 28 | oldClrType: typeof(string), 29 | oldMaxLength: 128); 30 | 31 | migrationBuilder.AlterColumn( 32 | name: "LoginProvider", 33 | table: "AspNetUserLogins", 34 | nullable: false, 35 | oldClrType: typeof(string), 36 | oldMaxLength: 128); 37 | 38 | migrationBuilder.CreateTable( 39 | name: "ShoppingCart", 40 | columns: table => new 41 | { 42 | Id = table.Column(nullable: false) 43 | .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 44 | ApplicationUserId = table.Column(nullable: true), 45 | MenuItemId = table.Column(nullable: false), 46 | Count = table.Column(nullable: false) 47 | }, 48 | constraints: table => 49 | { 50 | table.PrimaryKey("PK_ShoppingCart", x => x.Id); 51 | }); 52 | } 53 | 54 | protected override void Down(MigrationBuilder migrationBuilder) 55 | { 56 | migrationBuilder.DropTable( 57 | name: "ShoppingCart"); 58 | 59 | migrationBuilder.AlterColumn( 60 | name: "Name", 61 | table: "AspNetUserTokens", 62 | maxLength: 128, 63 | nullable: false, 64 | oldClrType: typeof(string)); 65 | 66 | migrationBuilder.AlterColumn( 67 | name: "LoginProvider", 68 | table: "AspNetUserTokens", 69 | maxLength: 128, 70 | nullable: false, 71 | oldClrType: typeof(string)); 72 | 73 | migrationBuilder.AlterColumn( 74 | name: "ProviderKey", 75 | table: "AspNetUserLogins", 76 | maxLength: 128, 77 | nullable: false, 78 | oldClrType: typeof(string)); 79 | 80 | migrationBuilder.AlterColumn( 81 | name: "LoginProvider", 82 | table: "AspNetUserLogins", 83 | maxLength: 128, 84 | nullable: false, 85 | oldClrType: typeof(string)); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Spice/Utility/SD.cs: -------------------------------------------------------------------------------- 1 | using Spice.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Spice.Utility 8 | { 9 | public static class SD 10 | { 11 | public const string DefaultFoodImage = "default_food.png"; 12 | 13 | 14 | public const string ManagerUser = "Manager"; 15 | public const string KitchenUser = "Kitchen"; 16 | public const string FrontDeskUser = "FrontDesk"; 17 | public const string CustomerEndUser = "Customer"; 18 | 19 | public const string ssShoppingCartCount = "ssCartCount"; 20 | public const string ssCouponCode = "ssCouponCode"; 21 | 22 | public const string StatusSubmitted = "Submitted"; 23 | public const string StatusInProcess = "Being Prepared"; 24 | public const string StatusReady = "Ready for Pickup"; 25 | public const string StatusCompleted = "Completed"; 26 | public const string StatusCancelled = "Cancelled"; 27 | 28 | public const string PaymentStatusPending = "Pending"; 29 | public const string PaymentStatusApproved = "Approved"; 30 | public const string PaymentStatusRejected = "Rejected"; 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | public static string ConvertToRawHtml(string source) 41 | { 42 | char[] array = new char[source.Length]; 43 | int arrayIndex = 0; 44 | bool inside = false; 45 | 46 | for (int i = 0; i < source.Length; i++) 47 | { 48 | char let = source[i]; 49 | if (let == '<') 50 | { 51 | inside = true; 52 | continue; 53 | } 54 | if (let == '>') 55 | { 56 | inside = false; 57 | continue; 58 | } 59 | if (!inside) 60 | { 61 | array[arrayIndex] = let; 62 | arrayIndex++; 63 | } 64 | } 65 | return new string(array, 0, arrayIndex); 66 | } 67 | 68 | public static double DiscountedPrice(Coupon couponFromDb, double OriginalOrderTotal) 69 | { 70 | if(couponFromDb==null) 71 | { 72 | return OriginalOrderTotal; 73 | } 74 | else 75 | { 76 | if(couponFromDb.MinimumAmount > OriginalOrderTotal) 77 | { 78 | return OriginalOrderTotal; 79 | } 80 | else 81 | { 82 | //everything is valid 83 | if(Convert.ToInt32(couponFromDb.CouponType) == (int)Coupon.ECouponType.Dollar) 84 | { 85 | //$10 off $100 86 | return Math.Round(OriginalOrderTotal - couponFromDb.Discount, 2); 87 | } 88 | if (Convert.ToInt32(couponFromDb.CouponType) == (int)Coupon.ECouponType.Percent) 89 | { 90 | //10% off $100 91 | return Math.Round(OriginalOrderTotal - (OriginalOrderTotal* couponFromDb.Discount/100), 2); 92 | } 93 | } 94 | } 95 | return OriginalOrderTotal; 96 | } 97 | 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/MenuItem/Details.cshtml: -------------------------------------------------------------------------------- 1 | @model Spice.Models.ViewModels.MenuItemViewModel 2 | 3 | @{ 4 | ViewData["Title"] = "Details"; 5 | } 6 | 7 | 8 |
      9 |

      Details Menu Item

      10 |
      11 |
      12 |
      13 |
      14 |
      15 |
      16 | 17 |
      18 |
      19 | 20 |
      21 |
      22 |
      23 |
      24 | 25 |
      26 |
      27 | @Html.TextAreaFor(m => m.MenuItem.Description) 28 |
      29 |
      30 |
      31 |
      32 | 33 |
      34 |
      35 | 36 |
      37 |
      38 | 39 |
      40 |
      41 | 42 |
      43 |
      44 | 45 |
      46 |
      47 |
      48 |
      49 | 50 |
      51 |
      52 | 53 |
      54 |
      55 |
      56 |
      57 | 58 |
      59 |
      60 | 61 |
      62 |
      63 |
      64 |
      65 |
      66 |
      67 | 68 |
      69 |
      70 |
      71 | 72 |
      73 |
      74 |
      75 | @section Scripts{ 76 | 84 | 85 | 86 | } 87 | -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/Coupon/Edit.cshtml: -------------------------------------------------------------------------------- 1 | @model Spice.Models.Coupon 2 | @{ 3 | ViewData["Title"] = "Edit"; 4 | } 5 | 6 |
      7 |

      Edit Coupon

      8 |
      9 |
      10 |
      11 | 12 |
      13 |
      14 | @{ 15 | var base64 = Convert.ToBase64String(Model.Picture); 16 | var imgsrc = string.Format("data:image/jpg;base64,{0}", base64); 17 | } 18 | 19 |
      20 |
      21 | 22 |
      23 |
      24 |
      25 | 26 |
      27 |
      28 | 29 |
      30 | 31 |
      32 |
      33 |
      34 | 35 |
      36 |
      37 | 38 |
      39 |
      40 |
      41 |
      42 | 43 |
      44 |
      45 | 46 |
      47 |
      48 |
      49 |
      50 | 51 |
      52 |
      53 | 54 |
      55 | 56 |
      57 |
      58 |
      59 | 60 |
      61 |
      62 | 63 |
      64 | 65 |
      66 |
      67 |
      68 | 69 |
      70 |
      71 | 72 |
      73 |
      74 |
      75 |
      76 |
      77 | 78 |
      79 |
      80 |
      81 | 82 |
      83 |
      -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Login.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model LoginModel 3 | 4 | @{ 5 | ViewData["Title"] = "Log in"; 6 | } 7 | 8 |

      @ViewData["Title"]

      9 |
      10 |
      11 |
      12 |
      13 |

      Use a local account to log in.

      14 |
      15 |
      16 |
      17 | 18 | 19 | 20 |
      21 |
      22 | 23 | 24 | 25 |
      26 |
      27 |
      28 | 32 |
      33 |
      34 |
      35 | 36 |
      37 |
      38 |

      39 | Forgot your password? 40 |

      41 |

      42 | Register as a new user 43 |

      44 |
      45 |
      46 |
      47 |
      48 |
      49 |
      50 |

      Use another service to log in.

      51 |
      52 | @{ 53 | if ((Model.ExternalLogins?.Count ?? 0) == 0) 54 | { 55 |
      56 |

      57 | There are no external authentication services configured. See this article 58 | for details on setting up this ASP.NET application to support logging in via external services. 59 |

      60 |
      61 | } 62 | else 63 | { 64 |
      65 |
      66 |

      67 | @foreach (var provider in Model.ExternalLogins) 68 | { 69 | 70 | } 71 |

      72 |
      73 |
      74 | } 75 | } 76 |
      77 |
      78 |
      79 | 80 | @section Scripts { 81 | 82 | } 83 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Authorization; 7 | using Microsoft.AspNetCore.Identity; 8 | using Microsoft.AspNetCore.Mvc; 9 | using Microsoft.AspNetCore.Mvc.RazorPages; 10 | using Microsoft.Extensions.Logging; 11 | 12 | namespace Spice.Areas.Identity.Pages.Account 13 | { 14 | [AllowAnonymous] 15 | public class LoginWith2faModel : PageModel 16 | { 17 | private readonly SignInManager _signInManager; 18 | private readonly ILogger _logger; 19 | 20 | public LoginWith2faModel(SignInManager signInManager, ILogger logger) 21 | { 22 | _signInManager = signInManager; 23 | _logger = logger; 24 | } 25 | 26 | [BindProperty] 27 | public InputModel Input { get; set; } 28 | 29 | public bool RememberMe { get; set; } 30 | 31 | public string ReturnUrl { get; set; } 32 | 33 | public class InputModel 34 | { 35 | [Required] 36 | [StringLength(7, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] 37 | [DataType(DataType.Text)] 38 | [Display(Name = "Authenticator code")] 39 | public string TwoFactorCode { get; set; } 40 | 41 | [Display(Name = "Remember this machine")] 42 | public bool RememberMachine { get; set; } 43 | } 44 | 45 | public async Task OnGetAsync(bool rememberMe, string returnUrl = null) 46 | { 47 | // Ensure the user has gone through the username & password screen first 48 | var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); 49 | 50 | if (user == null) 51 | { 52 | throw new InvalidOperationException($"Unable to load two-factor authentication user."); 53 | } 54 | 55 | ReturnUrl = returnUrl; 56 | RememberMe = rememberMe; 57 | 58 | return Page(); 59 | } 60 | 61 | public async Task OnPostAsync(bool rememberMe, string returnUrl = null) 62 | { 63 | if (!ModelState.IsValid) 64 | { 65 | return Page(); 66 | } 67 | 68 | returnUrl = returnUrl ?? Url.Content("~/"); 69 | 70 | var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); 71 | if (user == null) 72 | { 73 | throw new InvalidOperationException($"Unable to load two-factor authentication user."); 74 | } 75 | 76 | var authenticatorCode = Input.TwoFactorCode.Replace(" ", string.Empty).Replace("-", string.Empty); 77 | 78 | var result = await _signInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, rememberMe, Input.RememberMachine); 79 | 80 | if (result.Succeeded) 81 | { 82 | _logger.LogInformation("User with ID '{UserId}' logged in with 2fa.", user.Id); 83 | return LocalRedirect(returnUrl); 84 | } 85 | else if (result.IsLockedOut) 86 | { 87 | _logger.LogWarning("User with ID '{UserId}' account locked out.", user.Id); 88 | return RedirectToPage("./Lockout"); 89 | } 90 | else 91 | { 92 | _logger.LogWarning("Invalid authenticator code entered for user with ID '{UserId}'.", user.Id); 93 | ModelState.AddModelError(string.Empty, "Invalid authenticator code."); 94 | return Page(); 95 | } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Spice/Areas/Admin/Views/MenuItem/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @model Spice.Models.ViewModels.MenuItemViewModel 2 | 3 | @{ 4 | ViewData["Title"] = "Delete"; 5 | } 6 | 7 | 8 |
      9 |

      Delete Menu Item

      10 |
      11 |
      12 |
      13 |
      14 | 15 |
      16 |
      17 |
      18 | 19 |
      20 |
      21 | 22 |
      23 |
      24 |
      25 |
      26 | 27 |
      28 |
      29 | @Html.TextAreaFor(m => m.MenuItem.Description) 30 |
      31 |
      32 |
      33 |
      34 | 35 |
      36 |
      37 | 38 |
      39 |
      40 | 41 |
      42 |
      43 | 44 |
      45 |
      46 | 47 |
      48 |
      49 |
      50 |
      51 | 52 |
      53 |
      54 | 55 |
      56 |
      57 |
      58 |
      59 | 60 |
      61 |
      62 | 63 |
      64 |
      65 |
      66 |
      67 |
      68 |
      69 | 70 |
      71 |
      72 |
      73 | 74 |
      75 |
      76 |
      77 |
      78 | 79 | @section Scripts{ 80 | 88 | 89 | 90 | } 91 | -------------------------------------------------------------------------------- /Spice/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Identity; 7 | using Microsoft.AspNetCore.Mvc; 8 | using Microsoft.AspNetCore.Mvc.RazorPages; 9 | using Microsoft.Extensions.Logging; 10 | namespace Spice.Areas.Identity.Pages.Account.Manage 11 | { 12 | public class ChangePasswordModel : PageModel 13 | { 14 | private readonly UserManager _userManager; 15 | private readonly SignInManager _signInManager; 16 | private readonly ILogger _logger; 17 | 18 | public ChangePasswordModel( 19 | UserManager userManager, 20 | SignInManager signInManager, 21 | ILogger logger) 22 | { 23 | _userManager = userManager; 24 | _signInManager = signInManager; 25 | _logger = logger; 26 | } 27 | 28 | [BindProperty] 29 | public InputModel Input { get; set; } 30 | 31 | [TempData] 32 | public string StatusMessage { get; set; } 33 | 34 | public class InputModel 35 | { 36 | [Required] 37 | [DataType(DataType.Password)] 38 | [Display(Name = "Current password")] 39 | public string OldPassword { get; set; } 40 | 41 | [Required] 42 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] 43 | [DataType(DataType.Password)] 44 | [Display(Name = "New password")] 45 | public string NewPassword { get; set; } 46 | 47 | [DataType(DataType.Password)] 48 | [Display(Name = "Confirm new password")] 49 | [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] 50 | public string ConfirmPassword { get; set; } 51 | } 52 | 53 | public async Task OnGetAsync() 54 | { 55 | var user = await _userManager.GetUserAsync(User); 56 | if (user == null) 57 | { 58 | return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); 59 | } 60 | 61 | var hasPassword = await _userManager.HasPasswordAsync(user); 62 | if (!hasPassword) 63 | { 64 | return RedirectToPage("./SetPassword"); 65 | } 66 | 67 | return Page(); 68 | } 69 | 70 | public async Task OnPostAsync() 71 | { 72 | if (!ModelState.IsValid) 73 | { 74 | return Page(); 75 | } 76 | 77 | var user = await _userManager.GetUserAsync(User); 78 | if (user == null) 79 | { 80 | return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); 81 | } 82 | 83 | var changePasswordResult = await _userManager.ChangePasswordAsync(user, Input.OldPassword, Input.NewPassword); 84 | if (!changePasswordResult.Succeeded) 85 | { 86 | foreach (var error in changePasswordResult.Errors) 87 | { 88 | ModelState.AddModelError(string.Empty, error.Description); 89 | } 90 | return Page(); 91 | } 92 | 93 | await _signInManager.RefreshSignInAsync(user); 94 | _logger.LogInformation("User changed their password successfully."); 95 | StatusMessage = "Your password has been changed."; 96 | 97 | return RedirectToPage(); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /Spice/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Reboot v4.1.3 (https://getbootstrap.com/) 3 | * Copyright 2011-2018 The Bootstrap Authors 4 | * Copyright 2011-2018 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) 7 | */*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}@-ms-viewport{width:device-width}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important} 8 | /*# sourceMappingURL=bootstrap-reboot.min.css.map */ -------------------------------------------------------------------------------- /Spice/Areas/Admin/Controllers/CategoryController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Authorization; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.EntityFrameworkCore; 8 | using Spice.Data; 9 | using Spice.Models; 10 | using Spice.Utility; 11 | 12 | namespace Spice.Areas.Admin.Controllers 13 | { 14 | [Authorize(Roles = SD.ManagerUser)] 15 | [Area("Admin")] 16 | public class CategoryController : Controller 17 | { 18 | private readonly ApplicationDbContext _db; 19 | 20 | public CategoryController(ApplicationDbContext db) 21 | { 22 | _db = db; 23 | } 24 | 25 | 26 | //GET 27 | public async Task Index() 28 | { 29 | return View(await _db.Category.ToListAsync()); 30 | } 31 | 32 | //GET - CREATE 33 | public IActionResult Create() 34 | { 35 | return View(); 36 | } 37 | 38 | 39 | //POST - CREATE 40 | [HttpPost] 41 | [ValidateAntiForgeryToken] 42 | public async Task Create(Category category) 43 | { 44 | if(ModelState.IsValid) 45 | { 46 | //if valid 47 | _db.Category.Add(category); 48 | await _db.SaveChangesAsync(); 49 | 50 | return RedirectToAction(nameof(Index)); 51 | 52 | } 53 | return View(category); 54 | } 55 | 56 | 57 | //GET - EDIT 58 | public async Task Edit(int? id) 59 | { 60 | if(id==null) 61 | { 62 | return NotFound(); 63 | } 64 | var category = await _db.Category.FindAsync(id); 65 | if(category==null) 66 | { 67 | return NotFound(); 68 | } 69 | return View(category); 70 | 71 | } 72 | 73 | [HttpPost] 74 | [ValidateAntiForgeryToken] 75 | public async Task Edit(Category category) 76 | { 77 | if(ModelState.IsValid) 78 | { 79 | _db.Update(category); 80 | await _db.SaveChangesAsync(); 81 | 82 | return RedirectToAction(nameof(Index)); 83 | } 84 | return View(category); 85 | } 86 | 87 | 88 | 89 | //GET - DELETE 90 | public async Task Delete(int? id) 91 | { 92 | if (id == null) 93 | { 94 | return NotFound(); 95 | } 96 | var category = await _db.Category.FindAsync(id); 97 | if (category == null) 98 | { 99 | return NotFound(); 100 | } 101 | return View(category); 102 | } 103 | 104 | [HttpPost, ActionName("Delete")] 105 | [ValidateAntiForgeryToken] 106 | public async Task DeleteConfirmed(int? id) 107 | { 108 | var category = await _db.Category.FindAsync(id); 109 | 110 | if(category ==null) 111 | { 112 | return View(); 113 | } 114 | _db.Category.Remove(category); 115 | await _db.SaveChangesAsync(); 116 | return RedirectToAction(nameof(Index)); 117 | } 118 | 119 | //GET - DETAILS 120 | public async Task Details(int? id) 121 | { 122 | if (id == null) 123 | { 124 | return NotFound(); 125 | } 126 | 127 | var category = await _db.Category.FindAsync(id); 128 | if (category == null) 129 | { 130 | return NotFound(); 131 | } 132 | 133 | return View(category); 134 | } 135 | 136 | } 137 | } --------------------------------------------------------------------------------