using InboxIntel.Application.Abstractions; using InboxIntel.Domain.Entities; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace InboxIntel.Api.Controllers; public record WidgetLayoutDto(string WidgetKey, int X, int Y, int W, int H, bool Visible, int SortOrder, string? SettingsJson); /// Persists the user's draggable/resizable dashboard layout. public class WidgetLayoutController : ApiControllerBase { private readonly IAppDbContext _db; public WidgetLayoutController(IAppDbContext db) => _db = db; [HttpGet] public async Task Get(CancellationToken ct) { var layouts = await _db.WidgetLayouts .Where(w => w.UserId == UserId) .OrderBy(w => w.SortOrder) .Select(w => new WidgetLayoutDto(w.WidgetKey, w.X, w.Y, w.W, w.H, w.Visible, w.SortOrder, w.SettingsJson)) .ToListAsync(ct); return Ok(layouts); } /// Upserts the full layout for the user (replace semantics). [HttpPut] public async Task Save([FromBody] List layout, CancellationToken ct) { var existing = await _db.WidgetLayouts.Where(w => w.UserId == UserId).ToListAsync(ct); var byKey = existing.ToDictionary(w => w.WidgetKey); foreach (var dto in layout) { if (byKey.TryGetValue(dto.WidgetKey, out var w)) { w.X = dto.X; w.Y = dto.Y; w.W = dto.W; w.H = dto.H; w.Visible = dto.Visible; w.SortOrder = dto.SortOrder; w.SettingsJson = dto.SettingsJson; } else { _db.WidgetLayouts.Add(new WidgetLayout { UserId = UserId, WidgetKey = dto.WidgetKey, X = dto.X, Y = dto.Y, W = dto.W, H = dto.H, Visible = dto.Visible, SortOrder = dto.SortOrder, SettingsJson = dto.SettingsJson }); } } await _db.SaveChangesAsync(ct); return NoContent(); } }