feat: complete mealplanner app (backend + frontend + deployment)
.NET 8 backend with Zitadel JWT auth, TheMealDB integration, weekly meal plan generation, shopping list aggregation. Vue 3 + Tailwind 4 frontend with dark emerald theme, manual OIDC PKCE auth, all views implemented. Multi-stage Dockerfile with nginx reverse proxy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
71
backend/Data/AppDbContext.cs
Normal file
71
backend/Data/AppDbContext.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MealPlanner.Models;
|
||||
|
||||
namespace MealPlanner.Data;
|
||||
|
||||
public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
|
||||
{
|
||||
public DbSet<Recipe> Recipes => Set<Recipe>();
|
||||
public DbSet<RecipeIngredient> RecipeIngredients => Set<RecipeIngredient>();
|
||||
public DbSet<MealPlan> MealPlans => Set<MealPlan>();
|
||||
public DbSet<MealPlanEntry> MealPlanEntries => Set<MealPlanEntry>();
|
||||
public DbSet<UserSettings> UserSettings => Set<UserSettings>();
|
||||
public DbSet<CheckedShoppingItem> CheckedShoppingItems => Set<CheckedShoppingItem>();
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
// Recipe
|
||||
modelBuilder.Entity<Recipe>(e =>
|
||||
{
|
||||
e.HasKey(r => r.Id);
|
||||
e.HasIndex(r => r.UserId);
|
||||
e.HasIndex(r => r.ExternalId);
|
||||
e.HasMany(r => r.Ingredients)
|
||||
.WithOne(i => i.Recipe)
|
||||
.HasForeignKey(i => i.RecipeId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
// RecipeIngredient
|
||||
modelBuilder.Entity<RecipeIngredient>(e =>
|
||||
{
|
||||
e.HasKey(i => i.Id);
|
||||
});
|
||||
|
||||
// MealPlan
|
||||
modelBuilder.Entity<MealPlan>(e =>
|
||||
{
|
||||
e.HasKey(p => p.Id);
|
||||
e.HasIndex(p => new { p.UserId, p.WeekStart }).IsUnique();
|
||||
e.HasMany(p => p.Entries)
|
||||
.WithOne(en => en.MealPlan)
|
||||
.HasForeignKey(en => en.MealPlanId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
// MealPlanEntry
|
||||
modelBuilder.Entity<MealPlanEntry>(e =>
|
||||
{
|
||||
e.HasKey(en => en.Id);
|
||||
e.HasOne(en => en.Recipe)
|
||||
.WithMany()
|
||||
.HasForeignKey(en => en.RecipeId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
// UserSettings
|
||||
modelBuilder.Entity<UserSettings>(e =>
|
||||
{
|
||||
e.HasKey(s => s.UserId);
|
||||
});
|
||||
|
||||
// CheckedShoppingItem
|
||||
modelBuilder.Entity<CheckedShoppingItem>(e =>
|
||||
{
|
||||
e.HasKey(c => c.Id);
|
||||
e.HasIndex(c => new { c.MealPlanId, c.UserId, c.ItemName });
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user