This commit is contained in:
@@ -17,13 +17,155 @@ namespace Aberwyn.Controllers
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly IHostEnvironment _env;
|
||||
private readonly MenuService _menuService;
|
||||
private readonly ApplicationDbContext _context;
|
||||
|
||||
public FoodMenuController(IConfiguration configuration, IHostEnvironment env)
|
||||
public FoodMenuController(MenuService menuService, IConfiguration configuration, IHostEnvironment env, ApplicationDbContext context)
|
||||
{
|
||||
_menuService = menuService;
|
||||
_configuration = configuration;
|
||||
_env = env;
|
||||
_context = context;
|
||||
}
|
||||
[Authorize(Roles = "Budget")]
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult PizzaOrder()
|
||||
{
|
||||
var pizzas = _menuService.GetMealsByCategory("Pizza");
|
||||
ViewBag.Pizzas = pizzas;
|
||||
|
||||
int? lastId = HttpContext.Session.GetInt32("LastPizzaOrderId");
|
||||
if (lastId.HasValue)
|
||||
{
|
||||
var previousOrder = _context.PizzaOrders.FirstOrDefault(o => o.Id == lastId.Value);
|
||||
if (previousOrder != null)
|
||||
{
|
||||
ViewBag.PreviousOrder = previousOrder;
|
||||
}
|
||||
}
|
||||
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult EditPizzaOrder(int id)
|
||||
{
|
||||
var order = _context.PizzaOrders.FirstOrDefault(o => o.Id == id);
|
||||
if (order == null)
|
||||
{
|
||||
return RedirectToAction("PizzaOrder");
|
||||
}
|
||||
|
||||
// Sätt session så vi vet att det är en uppdatering
|
||||
HttpContext.Session.SetInt32("LastPizzaOrderId", order.Id);
|
||||
|
||||
// Visa formuläret
|
||||
TempData["ForceShowForm"] = "true";
|
||||
|
||||
return RedirectToAction("PizzaOrder");
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult ClearPizzaSession()
|
||||
{
|
||||
HttpContext.Session.Remove("LastPizzaOrderId");
|
||||
return RedirectToAction("PizzaOrder");
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult PizzaOrder(string customerName, string pizzaName, string ingredients, int? orderId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(customerName) || string.IsNullOrWhiteSpace(pizzaName))
|
||||
{
|
||||
TempData["Error"] = "Fyll i både namn och pizza!";
|
||||
return RedirectToAction("PizzaOrder");
|
||||
}
|
||||
|
||||
int? lastId = orderId ?? HttpContext.Session.GetInt32("LastPizzaOrderId");
|
||||
PizzaOrder order;
|
||||
|
||||
if (lastId.HasValue)
|
||||
{
|
||||
// Uppdatera befintlig order
|
||||
order = _context.PizzaOrders.FirstOrDefault(o => o.Id == lastId.Value);
|
||||
if (order != null)
|
||||
{
|
||||
order.CustomerName = customerName.Trim();
|
||||
order.PizzaName = pizzaName.Trim();
|
||||
order.IngredientsJson = ingredients;
|
||||
order.Status = "Ej bekräftad"; // återställ status om du vill
|
||||
_context.SaveChanges();
|
||||
|
||||
TempData["Success"] = $"Din beställning har uppdaterats!";
|
||||
return RedirectToAction("PizzaOrder");
|
||||
}
|
||||
}
|
||||
|
||||
// Annars skapa ny
|
||||
order = new PizzaOrder
|
||||
{
|
||||
CustomerName = customerName.Trim(),
|
||||
PizzaName = pizzaName.Trim(),
|
||||
IngredientsJson = ingredients,
|
||||
Status = "Ej bekräftad",
|
||||
OrderedAt = DateTime.Now
|
||||
};
|
||||
|
||||
_context.PizzaOrders.Add(order);
|
||||
_context.SaveChanges();
|
||||
TempData["ForceShowForm"] = "true";
|
||||
|
||||
|
||||
HttpContext.Session.SetInt32("LastPizzaOrderId", order.Id);
|
||||
|
||||
TempData["Success"] = $"Tack {order.CustomerName}! Din pizza är beställd!";
|
||||
return RedirectToAction("PizzaOrder");
|
||||
}
|
||||
|
||||
|
||||
|
||||
[Authorize(Roles = "Chef")]
|
||||
public IActionResult PizzaAdmin(DateTime? date)
|
||||
{
|
||||
var selectedDate = date ?? DateTime.Today;
|
||||
var nextDay = selectedDate.AddDays(1);
|
||||
|
||||
var allOrders = _context.PizzaOrders
|
||||
.Where(o => o.OrderedAt >= selectedDate && o.OrderedAt < nextDay)
|
||||
.OrderBy(o => o.OrderedAt)
|
||||
.ToList();
|
||||
|
||||
ViewBag.ActiveOrders = allOrders
|
||||
.Where(o => o.Status != "Klar")
|
||||
.ToList();
|
||||
|
||||
ViewBag.CompletedOrders = allOrders
|
||||
.Where(o => o.Status == "Klar")
|
||||
.ToList();
|
||||
|
||||
return View();
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Roles = "Chef")]
|
||||
public IActionResult UpdatePizzaOrder(int id, string status, string ingredientsJson)
|
||||
{
|
||||
var order = _context.PizzaOrders.FirstOrDefault(p => p.Id == id);
|
||||
if (order != null)
|
||||
{
|
||||
order.Status = status;
|
||||
order.IngredientsJson = ingredientsJson;
|
||||
_context.SaveChanges();
|
||||
}
|
||||
|
||||
return RedirectToAction("PizzaAdmin");
|
||||
}
|
||||
|
||||
[Authorize(Roles = "Chef")]
|
||||
public IActionResult Veckomeny(int? week, int? year)
|
||||
{
|
||||
var menuService = new MenuService(_configuration, _env);
|
||||
|
||||
15
Aberwyn/Controllers/LoginController.cs
Normal file
15
Aberwyn/Controllers/LoginController.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Aberwyn.Controllers
|
||||
{
|
||||
public class LoginController : Controller
|
||||
{
|
||||
[HttpGet]
|
||||
public IActionResult Login(string returnUrl = "/")
|
||||
{
|
||||
ViewBag.ReturnUrl = returnUrl;
|
||||
return View(); // View måste heta "Login.cshtml"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
58
Aberwyn/Controllers/PizzaController.cs
Normal file
58
Aberwyn/Controllers/PizzaController.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Aberwyn.Data;
|
||||
using Aberwyn.Models;
|
||||
using System.Linq;
|
||||
|
||||
namespace Aberwyn.Controllers
|
||||
{
|
||||
public class PizzaController : Controller
|
||||
{
|
||||
private readonly MenuService _menuService;
|
||||
private readonly ApplicationDbContext _context;
|
||||
|
||||
public PizzaController(MenuService menuService, ApplicationDbContext context)
|
||||
{
|
||||
_menuService = menuService;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Order()
|
||||
{
|
||||
var pizzas = _menuService.GetMeals()
|
||||
.Where(m => m.Name.ToLower().Contains("pizza"))
|
||||
.OrderBy(m => m.Name)
|
||||
.ToList();
|
||||
|
||||
var orders = _context.PizzaOrders
|
||||
.OrderByDescending(o => o.OrderedAt)
|
||||
.ToList();
|
||||
|
||||
ViewBag.Pizzas = pizzas;
|
||||
ViewBag.ExistingOrders = orders;
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Order(string customerName, string pizzaName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(customerName) || string.IsNullOrWhiteSpace(pizzaName))
|
||||
{
|
||||
TempData["Error"] = "Både namn och pizza måste anges.";
|
||||
return RedirectToAction("Order");
|
||||
}
|
||||
|
||||
var order = new PizzaOrder
|
||||
{
|
||||
CustomerName = customerName.Trim(),
|
||||
PizzaName = pizzaName.Trim()
|
||||
};
|
||||
|
||||
_context.PizzaOrders.Add(order);
|
||||
_context.SaveChanges();
|
||||
|
||||
TempData["Success"] = "Beställningen har lagts!";
|
||||
return RedirectToAction("Order");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,5 +15,7 @@ namespace Aberwyn.Data
|
||||
public DbSet<BudgetCategory> BudgetCategories { get; set; }
|
||||
public DbSet<BudgetItem> BudgetItems { get; set; }
|
||||
public DbSet<PushSubscriber> PushSubscribers { get; set; }
|
||||
public DbSet<PizzaOrder> PizzaOrders { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -471,6 +471,61 @@ namespace Aberwyn.Data
|
||||
SaveIngredients(meal.Id, meal.Ingredients);
|
||||
}
|
||||
}
|
||||
public List<Meal> GetMealsByCategory(string category)
|
||||
{
|
||||
var meals = new List<Meal>();
|
||||
|
||||
using var connection = GetConnection();
|
||||
connection.Open();
|
||||
|
||||
string query = @"
|
||||
SELECT m.Id, m.Name, m.Category, m.Description, m.ImageUrl, m.ImageData, m.ImageMimeType,
|
||||
i.Id AS IngredientId, i.Quantity, i.Item
|
||||
FROM Meals m
|
||||
LEFT JOIN Ingredients i ON m.Id = i.MealId
|
||||
WHERE m.Category = @category
|
||||
ORDER BY m.Name, i.Id";
|
||||
|
||||
using var cmd = new MySqlCommand(query, connection);
|
||||
cmd.Parameters.AddWithValue("@category", category);
|
||||
|
||||
using var reader = cmd.ExecuteReader();
|
||||
Dictionary<int, Meal> mealMap = new();
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
int mealId = reader.GetInt32("Id");
|
||||
|
||||
if (!mealMap.ContainsKey(mealId))
|
||||
{
|
||||
mealMap[mealId] = new Meal
|
||||
{
|
||||
Id = mealId,
|
||||
Name = reader.GetString("Name"),
|
||||
Category = reader.IsDBNull(reader.GetOrdinal("Category")) ? null : reader.GetString("Category"),
|
||||
Description = reader.IsDBNull(reader.GetOrdinal("Description")) ? null : reader.GetString("Description"),
|
||||
ImageUrl = reader.IsDBNull(reader.GetOrdinal("ImageUrl")) ? null : reader.GetString("ImageUrl"),
|
||||
ImageData = reader.IsDBNull(reader.GetOrdinal("ImageData")) ? null : (byte[])reader["ImageData"],
|
||||
ImageMimeType = reader.IsDBNull(reader.GetOrdinal("ImageMimeType")) ? null : reader.GetString("ImageMimeType"),
|
||||
Ingredients = new List<Ingredient>()
|
||||
};
|
||||
}
|
||||
|
||||
if (!reader.IsDBNull(reader.GetOrdinal("IngredientId")))
|
||||
{
|
||||
mealMap[mealId].Ingredients.Add(new Ingredient
|
||||
{
|
||||
Id = reader.GetInt32("IngredientId"),
|
||||
MealId = mealId,
|
||||
Quantity = reader.IsDBNull(reader.GetOrdinal("Quantity")) ? "" : reader.GetString("Quantity"),
|
||||
Item = reader.IsDBNull(reader.GetOrdinal("Item")) ? "" : reader.GetString("Item")
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return mealMap.Values.ToList();
|
||||
}
|
||||
|
||||
public List<WeeklyMenu> GetMenuEntriesByDateRange(DateTime startDate, DateTime endDate)
|
||||
{
|
||||
var results = new List<WeeklyMenu>();
|
||||
|
||||
403
Aberwyn/Migrations/20250524103706_AddPizzaOrder.Designer.cs
generated
Normal file
403
Aberwyn/Migrations/20250524103706_AddPizzaOrder.Designer.cs
generated
Normal file
@@ -0,0 +1,403 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Aberwyn.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20250524103706_AddPizzaOrder")]
|
||||
partial class AddPizzaOrder
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "6.0.36")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("BudgetPeriodId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Color")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetPeriodId");
|
||||
|
||||
b.ToTable("BudgetCategories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasColumnType("decimal(65,30)");
|
||||
|
||||
b.Property<int>("BudgetCategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IncludeInSummary")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsExpense")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetCategoryId");
|
||||
|
||||
b.ToTable("BudgetItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Month")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Year")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BudgetPeriods");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PushSubscriber", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Auth")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Endpoint")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("P256DH")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PushSubscribers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetPeriod", "BudgetPeriod")
|
||||
.WithMany("Categories")
|
||||
.HasForeignKey("BudgetPeriodId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetPeriod");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetCategory", "BudgetCategory")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("BudgetCategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetCategory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Navigation("Categories");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
19
Aberwyn/Migrations/20250524103706_AddPizzaOrder.cs
Normal file
19
Aberwyn/Migrations/20250524103706_AddPizzaOrder.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddPizzaOrder : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
432
Aberwyn/Migrations/20250524121511_AddPizzaOrderTable.Designer.cs
generated
Normal file
432
Aberwyn/Migrations/20250524121511_AddPizzaOrderTable.Designer.cs
generated
Normal file
@@ -0,0 +1,432 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Aberwyn.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20250524121511_AddPizzaOrderTable")]
|
||||
partial class AddPizzaOrderTable
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "6.0.36")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.ApplicationUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("BudgetPeriodId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Color")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetPeriodId");
|
||||
|
||||
b.ToTable("BudgetCategories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasColumnType("decimal(65,30)");
|
||||
|
||||
b.Property<int>("BudgetCategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IncludeInSummary")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<bool>("IsExpense")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("BudgetCategoryId");
|
||||
|
||||
b.ToTable("BudgetItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Month")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Year")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("BudgetPeriods");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PizzaOrder", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("CustomerName")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("IngredientsJson")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("OrderedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("PizzaName")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PizzaOrders");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PushSubscriber", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Auth")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Endpoint")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("P256DH")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PushSubscribers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("varchar(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetPeriod", "BudgetPeriod")
|
||||
.WithMany("Categories")
|
||||
.HasForeignKey("BudgetPeriodId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetPeriod");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetItem", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.BudgetCategory", "BudgetCategory")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("BudgetCategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("BudgetCategory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.HasOne("Aberwyn.Models.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetCategory", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.BudgetPeriod", b =>
|
||||
{
|
||||
b.Navigation("Categories");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
42
Aberwyn/Migrations/20250524121511_AddPizzaOrderTable.cs
Normal file
42
Aberwyn/Migrations/20250524121511_AddPizzaOrderTable.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aberwyn.Migrations
|
||||
{
|
||||
public partial class AddPizzaOrderTable : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PizzaOrders",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
CustomerName = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
PizzaName = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
IngredientsJson = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Status = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
OrderedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PizzaOrders", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "PizzaOrders");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -162,6 +162,35 @@ namespace Aberwyn.Migrations
|
||||
b.ToTable("BudgetPeriods");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PizzaOrder", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("CustomerName")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("IngredientsJson")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<DateTime>("OrderedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("PizzaName")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PizzaOrders");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aberwyn.Models.PushSubscriber", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace Aberwyn.Models
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string ProteinType { get; set; }
|
||||
public string Category { get; set; }
|
||||
public string CarbType { get; set; }
|
||||
public string RecipeUrl { get; set; }
|
||||
public string ImageUrl { get; set; }
|
||||
@@ -61,6 +62,8 @@ namespace Aberwyn.Models
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Category { get; set; }
|
||||
|
||||
public string? ImageUrl { get; set; }
|
||||
public string? ImageData { get; set; } // base64
|
||||
public string? ImageMimeType { get; set; }
|
||||
@@ -71,6 +74,7 @@ namespace Aberwyn.Models
|
||||
{
|
||||
Id = meal.Id,
|
||||
Name = meal.Name,
|
||||
Category = meal.Category,
|
||||
ImageUrl = meal.ImageUrl,
|
||||
ImageMimeType = meal.ImageMimeType,
|
||||
ImageData = meal.ImageData != null ? Convert.ToBase64String(meal.ImageData) : null
|
||||
|
||||
22
Aberwyn/Models/PizzaOrder.cs
Normal file
22
Aberwyn/Models/PizzaOrder.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Aberwyn.Models
|
||||
{
|
||||
public class PizzaOrder
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
[Required]
|
||||
public string CustomerName { get; set; }
|
||||
|
||||
[Required]
|
||||
public string PizzaName { get; set; }
|
||||
|
||||
public string? IngredientsJson { get; set; } // lista i JSON-form
|
||||
|
||||
public string Status { get; set; } = "Ej bekräftad"; // "Ej bekräftad", "Bekräftad", "Klar"
|
||||
|
||||
public DateTime OrderedAt { get; set; } = DateTime.Now;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,6 +21,12 @@ builder.Services.AddControllersWithViews()
|
||||
// Ignorera null-v<>rden vid serialisering
|
||||
opts.JsonSerializerOptions.IgnoreNullValues = true;
|
||||
});
|
||||
builder.Services.AddSession(options =>
|
||||
{
|
||||
options.IdleTimeout = TimeSpan.FromHours(1);
|
||||
options.Cookie.HttpOnly = true;
|
||||
options.Cookie.IsEssential = true;
|
||||
});
|
||||
|
||||
builder.Services.AddRazorPages();
|
||||
builder.Services.AddHttpClient();
|
||||
@@ -64,8 +70,10 @@ builder.Services.AddSingleton<PushNotificationService>(sp =>
|
||||
});
|
||||
|
||||
builder.Services.Configure<VapidOptions>(builder.Configuration.GetSection("Vapid"));
|
||||
|
||||
|
||||
builder.Services.ConfigureApplicationCookie(options =>
|
||||
{
|
||||
options.LoginPath = "/Identity/Account/Login"; // korrekt för ditt nuvarande upplägg
|
||||
});
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
builder.Services.Configure<RequestLocalizationOptions>(options =>
|
||||
{
|
||||
@@ -99,6 +107,7 @@ if (!app.Environment.IsDevelopment())
|
||||
|
||||
app.UseStaticFiles();
|
||||
app.UseRouting();
|
||||
app.UseSession();
|
||||
app.UseAuthentication();;
|
||||
app.UseAuthorization();
|
||||
|
||||
|
||||
145
Aberwyn/Views/FoodMenu/PizzaAdmin.cshtml
Normal file
145
Aberwyn/Views/FoodMenu/PizzaAdmin.cshtml
Normal file
@@ -0,0 +1,145 @@
|
||||
@using Newtonsoft.Json
|
||||
@using Newtonsoft.Json.Serialization
|
||||
@{
|
||||
ViewData["Title"] = "Pizza Admin";
|
||||
var activeOrders = ViewBag.ActiveOrders as List<PizzaOrder> ?? new List<PizzaOrder>();
|
||||
var completedOrders = ViewBag.CompletedOrders as List<PizzaOrder> ?? new List<PizzaOrder>();
|
||||
}
|
||||
|
||||
<style>
|
||||
.card {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
|
||||
transition: transform 0.2s ease-in-out;
|
||||
background-color: #f8f9fa;
|
||||
flex: 1 1 260px;
|
||||
min-width: 240px;
|
||||
max-width: 280px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
font-weight: bold;
|
||||
padding: 10px 12px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.card-body {
|
||||
padding: 12px;
|
||||
flex-grow: 1;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.border-info .card-header {
|
||||
background-color: #0dcaf0;
|
||||
}
|
||||
|
||||
.border-warning .card-header {
|
||||
background-color: #ffc107;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.border-success .card-header {
|
||||
background-color: #28a745;
|
||||
}
|
||||
|
||||
.card .btn {
|
||||
font-weight: 600;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.card ul {
|
||||
margin-bottom: 0;
|
||||
padding-left: 1.2rem;
|
||||
}
|
||||
|
||||
.card-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
@@media only screen and (max-width: 600px) {
|
||||
.card {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<h2 class="mt-4">Aktiva beställningar</h2>
|
||||
<div class="card-grid">
|
||||
@foreach (var order in activeOrders)
|
||||
{
|
||||
var ingredients = new List<string>();
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(order.IngredientsJson))
|
||||
{
|
||||
ingredients = System.Text.Json.JsonSerializer.Deserialize<List<string>>(order.IngredientsJson);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
ingredients = order.IngredientsJson.Split('\n').ToList();
|
||||
}
|
||||
|
||||
var cardClass = order.Status switch
|
||||
{
|
||||
"Bekräftad" => "border-warning",
|
||||
"Klar" => "border-success",
|
||||
_ => "border-info"
|
||||
};
|
||||
|
||||
<div class="card @cardClass">
|
||||
<div class="card-header">@order.CustomerName</div>
|
||||
<div class="card-body">
|
||||
<div class="fw-bold mb-1">@order.PizzaName</div>
|
||||
<ul class="mb-2">
|
||||
@foreach (var ing in ingredients)
|
||||
{
|
||||
<li>@ing</li>
|
||||
}
|
||||
</ul>
|
||||
<form id="form-@order.Id" method="post" asp-action="UpdatePizzaOrder">
|
||||
<input type="hidden" name="id" value="@order.Id" />
|
||||
<input type="hidden" name="ingredientsJson" value='@System.Text.Json.JsonSerializer.Serialize(ingredients)' />
|
||||
<div class="d-flex gap-2">
|
||||
@if (order.Status == "Ej bekräftad")
|
||||
{
|
||||
<input type="hidden" name="status" value="Bekräftad" />
|
||||
<button type="submit" class="btn btn-sm btn-outline-primary">Bekräfta</button>
|
||||
}
|
||||
else if (order.Status == "Bekräftad")
|
||||
{
|
||||
<input type="hidden" name="status" value="Klar" />
|
||||
<button type="submit" class="btn btn-sm btn-outline-success">✔ Klar</button>
|
||||
}
|
||||
<button type="submit" formaction="@Url.Action("UpdatePizzaOrder", new { status = "Neka", id = order.Id })" class="btn btn-sm btn-outline-danger">Neka</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<h2 class="mt-5">Färdiga pizzor</h2>
|
||||
@if (completedOrders.Any())
|
||||
{
|
||||
<ul class="list-group">
|
||||
@foreach (var order in completedOrders)
|
||||
{
|
||||
<li class="list-group-item">
|
||||
@order.CustomerName – @order.PizzaName
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="text-muted">Inga pizzor är klara ännu.</div>
|
||||
}
|
||||
226
Aberwyn/Views/FoodMenu/PizzaOrder.cshtml
Normal file
226
Aberwyn/Views/FoodMenu/PizzaOrder.cshtml
Normal file
@@ -0,0 +1,226 @@
|
||||
@using Newtonsoft.Json
|
||||
@using Newtonsoft.Json.Serialization
|
||||
@{
|
||||
ViewData["Title"] = "Beställ pizza";
|
||||
var pizzas = ViewBag.Pizzas as List<Meal>;
|
||||
var previousOrder = ViewBag.PreviousOrder as PizzaOrder;
|
||||
var lastId = Context.Session.GetInt32("LastPizzaOrderId");
|
||||
var isCurrentOrder = previousOrder?.Id == lastId;
|
||||
var forceShow = TempData["ForceShowForm"]?.ToString() == "true";
|
||||
var justOrdered = TempData["Success"]?.ToString()?.Contains("beställd") == true;
|
||||
var showForm = previousOrder == null || (forceShow && !justOrdered);
|
||||
|
||||
}
|
||||
|
||||
<link rel="stylesheet" href="~/css/pizza.css" />
|
||||
|
||||
<div class="pizza-container">
|
||||
|
||||
@if (TempData["Success"] != null)
|
||||
{
|
||||
<div class="alert alert-success text-center mb-4">
|
||||
🍕 @TempData["Success"]
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (previousOrder != null)
|
||||
{
|
||||
var ingredienser = string.IsNullOrEmpty(previousOrder.IngredientsJson)
|
||||
? new List<string>()
|
||||
: System.Text.Json.JsonSerializer.Deserialize<List<string>>(previousOrder.IngredientsJson);
|
||||
|
||||
<div class="alert alert-info mb-4">
|
||||
<strong>🍕 Du har redan beställt:</strong><br />
|
||||
<strong>@previousOrder.PizzaName</strong>
|
||||
@if (ingredienser.Count > 0)
|
||||
{
|
||||
<span>(med @string.Join(", ", ingredienser))</span>
|
||||
}
|
||||
<div class="mt-2">
|
||||
<span class="badge bg-secondary">Status: @previousOrder.Status</span>
|
||||
</div>
|
||||
<form method="get" asp-action="EditPizzaOrder" asp-route-id="@previousOrder.Id" class="d-inline mt-2">
|
||||
<button class="btn btn-sm btn-outline-primary me-2">✏️ Uppdatera min beställning</button>
|
||||
</form>
|
||||
<form method="post" asp-action="ClearPizzaSession" class="d-inline">
|
||||
<button class="btn btn-sm btn-outline-secondary">➕ Beställ ny pizza</button>
|
||||
</form>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (showForm)
|
||||
{
|
||||
<!-- Steg 1: Namn -->
|
||||
<div id="step1" class="pizza-step active">
|
||||
<h2>Hej! Vad heter du? 😊</h2>
|
||||
<input type="text" id="customerName" placeholder="Ditt namn" class="form-control" />
|
||||
<button onclick="goToStep(2)" class="btn btn-primary mt-3">Fortsätt</button>
|
||||
</div>
|
||||
|
||||
<!-- Steg 2: Välj pizza -->
|
||||
<div id="step2" class="pizza-step">
|
||||
<h2>🍕 Välj en pizza</h2>
|
||||
<div class="pizza-list">
|
||||
@foreach (var pizza in pizzas)
|
||||
{
|
||||
<div class="pizza-card" onclick="selectPizza(@pizza.Id)">
|
||||
<h3>@pizza.Name</h3>
|
||||
<p>@string.Join(", ", pizza.Ingredients?.Select(i => i.Item) ?? new List<string>())</p>
|
||||
</div>
|
||||
}
|
||||
<div class="pizza-card custom" onclick="selectPizza(null)">
|
||||
<h3>🧑🍳 Skapa egen pizza</h3>
|
||||
<p>Lägg till dina egna ingredienser</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Steg 3: Redigera ingredienser -->
|
||||
<div id="step3" class="pizza-step">
|
||||
<h2 id="editTitle">Redigera pizza</h2>
|
||||
<ul id="ingredientList" class="list-group mb-3"></ul>
|
||||
<div class="input-group mb-3">
|
||||
<input type="text" id="newIngredient" class="form-control" placeholder="Lägg till ingrediens" />
|
||||
<button type="button" class="btn btn-outline-secondary" onclick="addIngredient()">➕</button>
|
||||
</div>
|
||||
<button class="btn btn-secondary" onclick="goToStep(2)">⬅ Tillbaka</button>
|
||||
<button class="btn btn-primary" onclick="goToStep(4)">Fortsätt</button>
|
||||
</div>
|
||||
|
||||
<!-- Steg 4: Summering -->
|
||||
<div id="step4" class="pizza-step">
|
||||
<h2>Bekräfta din beställning</h2>
|
||||
<p>Din pizza:</p>
|
||||
<p><strong id="summaryPizza"></strong></p>
|
||||
<ul id="summaryIngredients" class="list-group mb-3"></ul>
|
||||
|
||||
<form method="post">
|
||||
<input type="hidden" name="customerName" id="formName" />
|
||||
<input type="hidden" name="pizzaName" id="formPizza" />
|
||||
<input type="hidden" name="ingredients" id="formIngredients" />
|
||||
<button type="submit" class="btn btn-success">✅ Skicka beställning</button>
|
||||
</form>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
<script>
|
||||
@if (ViewBag.PreviousOrder is PizzaOrder p)
|
||||
{
|
||||
<text>
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
const forceEdit = @((TempData["ForceShowForm"]?.ToString() == "true").ToString().ToLower());
|
||||
const customerField = document.getElementById("customerName");
|
||||
if (customerField) customerField.value = "@p.CustomerName";
|
||||
const selected = allMeals.find(m => m.name === "@p.PizzaName") || { name: "Egen pizza", ingredients: [] };
|
||||
if (forceEdit && selected) {
|
||||
selectedPizza = selected;
|
||||
selectedIngredients = @Html.Raw(p.IngredientsJson ?? "[]");
|
||||
document.getElementById("editTitle").innerText = `Redigera: ${selected.name}`;
|
||||
renderIngredientList();
|
||||
selectedName = "@p.CustomerName";
|
||||
goToStep(3);
|
||||
}
|
||||
});
|
||||
</text>
|
||||
}
|
||||
|
||||
const allMeals = @Html.Raw(JsonConvert.SerializeObject(
|
||||
pizzas,
|
||||
new JsonSerializerSettings {
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
ContractResolver = new CamelCasePropertyNamesContractResolver()
|
||||
}));
|
||||
|
||||
let selectedPizza = null;
|
||||
let selectedIngredients = [];
|
||||
let selectedName = "";
|
||||
|
||||
function goToStep(step) {
|
||||
if (step === 2) {
|
||||
const nameInput = document.getElementById("customerName").value.trim();
|
||||
if (!nameInput) {
|
||||
alert("Skriv ditt namn!");
|
||||
return;
|
||||
}
|
||||
selectedName = nameInput;
|
||||
}
|
||||
|
||||
if (step === 4) {
|
||||
const pizzaName = selectedPizza?.name ?? "Egen pizza";
|
||||
const originalIngredients = selectedPizza?.ingredients?.map(i => i.item) ?? [];
|
||||
const current = selectedIngredients;
|
||||
|
||||
const removed = [];
|
||||
const added = [];
|
||||
|
||||
let details = [];
|
||||
if (removed.length > 0) details.push("utan " + removed.join(", "));
|
||||
if (added.length > 0) details.push("extra " + added.join(", "));
|
||||
|
||||
const fullName = details.length > 0
|
||||
? `${pizzaName} (${details.join(", ")})`
|
||||
: pizzaName;
|
||||
|
||||
document.getElementById("summaryPizza").innerText = fullName;
|
||||
document.getElementById("formName").value = selectedName;
|
||||
document.getElementById("formPizza").value = fullName;
|
||||
document.getElementById("formIngredients").value = JSON.stringify(selectedIngredients);
|
||||
const list = document.getElementById("summaryIngredients");
|
||||
list.innerHTML = '';
|
||||
selectedIngredients.forEach(ing => {
|
||||
const li = document.createElement("li");
|
||||
li.className = "list-group-item";
|
||||
li.innerText = ing;
|
||||
list.appendChild(li);
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelectorAll(".pizza-step").forEach(s => s.classList.remove("active"));
|
||||
document.getElementById(`step${step}`)?.classList.add("active");
|
||||
}
|
||||
|
||||
function selectPizza(pizzaId) {
|
||||
pizzaId = parseInt(pizzaId);
|
||||
selectedPizza = allMeals.find(m => m.id === pizzaId);
|
||||
if (!selectedPizza) {
|
||||
selectedPizza = { name: "Egen pizza", ingredients: [] };
|
||||
}
|
||||
selectedIngredients = [...(selectedPizza.ingredients?.map(i => i.item) ?? [])];
|
||||
document.getElementById("editTitle").innerText = `Redigera: ${selectedPizza.name}`;
|
||||
renderIngredientList();
|
||||
goToStep(3);
|
||||
}
|
||||
|
||||
function renderIngredientList() {
|
||||
const list = document.getElementById("ingredientList");
|
||||
list.innerHTML = '';
|
||||
selectedIngredients.forEach((ing, i) => {
|
||||
const li = document.createElement("li");
|
||||
li.className = "list-group-item d-flex justify-content-between";
|
||||
li.innerHTML = `${ing} <button class="btn btn-sm btn-danger" onclick="removeIngredient(${i})">🗑</button>`;
|
||||
list.appendChild(li);
|
||||
});
|
||||
}
|
||||
|
||||
function addIngredient() {
|
||||
const input = document.getElementById("newIngredient");
|
||||
const value = input.value.trim();
|
||||
if (value) {
|
||||
selectedIngredients.push(value);
|
||||
input.value = '';
|
||||
renderIngredientList();
|
||||
}
|
||||
}
|
||||
|
||||
function removeIngredient(index) {
|
||||
selectedIngredients.splice(index, 1);
|
||||
renderIngredientList();
|
||||
}
|
||||
|
||||
document.getElementById("customerName")?.addEventListener("keydown", function (e) {
|
||||
if (e.key === "Enter") goToStep(2);
|
||||
});
|
||||
</script>
|
||||
}
|
||||
21
Aberwyn/Views/Login/Index.cshtml
Normal file
21
Aberwyn/Views/Login/Index.cshtml
Normal file
@@ -0,0 +1,21 @@
|
||||
@{
|
||||
ViewData["Title"] = "Logga in";
|
||||
var returnUrl = ViewBag.ReturnUrl as string ?? "/";
|
||||
}
|
||||
|
||||
<h2>Logga in</h2>
|
||||
|
||||
<form method="post" asp-area="Identity" asp-page="/Account/Login">
|
||||
<input type="hidden" name="returnUrl" value="@returnUrl" />
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="username" class="form-label">Användarnamn</label>
|
||||
<input type="text" class="form-control" id="username" name="username" required />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Lösenord</label>
|
||||
<input type="password" class="form-control" id="password" name="password" required />
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Logga in</button>
|
||||
</form>
|
||||
174
Aberwyn/wwwroot/css/pizza.css
Normal file
174
Aberwyn/wwwroot/css/pizza.css
Normal file
@@ -0,0 +1,174 @@
|
||||
/* === PIZZERIA-INSPIRERAD STIL === */
|
||||
|
||||
.pizza-step {
|
||||
display: none;
|
||||
background-color: #fffaf0;
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
box-shadow: 0 4px 10px rgba(0,0,0,0.1);
|
||||
max-width: 600px;
|
||||
margin: 2rem auto;
|
||||
animation: fadeIn 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.pizza-step.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.pizza-step h2,
|
||||
#editTitle {
|
||||
font-family: 'Georgia', serif;
|
||||
font-size: 1.8rem;
|
||||
color: #a00000;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
/* === PIZZA LISTA === */
|
||||
|
||||
.pizza-list {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
@media (min-width: 600px) {
|
||||
.pizza-list {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.pizza-card {
|
||||
border: 2px solid #f4d5b3;
|
||||
border-radius: 10px;
|
||||
background: #fff8e1;
|
||||
padding: 12px;
|
||||
cursor: pointer;
|
||||
transition: transform 0.2s ease, border-color 0.2s;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.pizza-card:hover {
|
||||
border-color: #e63946;
|
||||
transform: scale(1.02);
|
||||
background-color: #fff0dc;
|
||||
}
|
||||
|
||||
.pizza-card h3 {
|
||||
margin: 0;
|
||||
color: #b30000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.pizza-card p {
|
||||
font-size: 0.9rem;
|
||||
color: #555;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
/* === INGREDIENSER === */
|
||||
|
||||
#ingredientList {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
#ingredientList .list-group-item {
|
||||
border: none;
|
||||
border-bottom: 1px dashed #ccc;
|
||||
font-family: 'Segoe UI', sans-serif;
|
||||
font-size: 1rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 6px 0;
|
||||
}
|
||||
|
||||
/* === KNAPPAR === */
|
||||
|
||||
.btn {
|
||||
font-weight: bold;
|
||||
border-radius: 6px;
|
||||
padding: 8px 16px;
|
||||
font-size: 1rem;
|
||||
font-family: 'Segoe UI', sans-serif;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.btn-outline-secondary,
|
||||
.btn-outline-primary,
|
||||
.btn-outline-danger {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.btn-outline-secondary {
|
||||
border: 2px solid #6a0dad;
|
||||
color: #6a0dad;
|
||||
}
|
||||
|
||||
.btn-outline-secondary:hover {
|
||||
background-color: #6a0dad;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary,
|
||||
.btn-success {
|
||||
background-color: #b30000;
|
||||
border: 2px solid #b30000;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover,
|
||||
.btn-success:hover {
|
||||
background-color: #cc0000;
|
||||
border-color: #cc0000;
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
background-color: #218838;
|
||||
border-color: #218838;
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background-color: #dc3545;
|
||||
border-color: #dc3545;
|
||||
}
|
||||
|
||||
.btn-danger:hover {
|
||||
background-color: #c82333;
|
||||
border-color: #bd2130;
|
||||
}
|
||||
|
||||
/* === FORM INPUT === */
|
||||
|
||||
.input-group input,
|
||||
.input-group button {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.input-group button {
|
||||
border-radius: 6px;
|
||||
border: 2px solid #6a0dad;
|
||||
background-color: white;
|
||||
color: #6a0dad;
|
||||
}
|
||||
|
||||
.input-group button:hover {
|
||||
background-color: #6a0dad;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* === ANIMATION === */
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
const urlsToCache = [
|
||||
'/',
|
||||
'/css/site.css',
|
||||
'/js/site.js',
|
||||
'/images/lewel-icon.png',
|
||||
'/manifest.json'
|
||||
];
|
||||
@@ -15,12 +14,22 @@ self.addEventListener('install', event => {
|
||||
);
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', event => {
|
||||
self.addEventListener("fetch", function (event) {
|
||||
const url = new URL(event.request.url);
|
||||
|
||||
// Hoppa över root / om du inte vill cachea den
|
||||
if (url.pathname === "/") {
|
||||
return;
|
||||
}
|
||||
|
||||
// Annars cacha som vanligt
|
||||
event.respondWith(
|
||||
caches.match(event.request)
|
||||
.then(response => response || fetch(event.request))
|
||||
caches.match(event.request).then(function (response) {
|
||||
return response || fetch(event.request);
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
self.addEventListener('push', function (event) {
|
||||
console.log("📨 Push event mottagen!", event);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user