feat: Add Lawn Care Tips section and improve Dashboard layout
This commit introduces a new "Lawn Care Tips" section to the application and refines the visual layout of the main Dashboard.
**Key Changes:**
*   **Lawn Care Tips Feature:**
    *   Added `LawnCareTip` model with `Title`, `Category`, and `Content` properties.
    *   Defined `TipCategory` enum for better organization (Mowing, Watering, Fertilizing, Weed Control, Aeration, General).
    *   Integrated `LawnCareTip` into `ApplicationDbContext` for database persistence.
    *   Updated `_Layout.cshtml` to include a new "Lawn Tips" navigation link.
*   **Dashboard Layout Fix:**
    *   Refactored `Views/Home/Index.cshtml` to correctly use Bootstrap's grid system by placing the "Log a New Activity" card in its own `div.row`. This resolves the layout issue where the card was appearing immediately after the previous row without proper spacing.
    *   Updated `HomeController` to include a `LastAerationDate` query for the dashboard display.
    *   Modified `DashboardViewModel` to include `LastAerationDate`.
*   **Build/Dependency Updates:**
    *   Added `Microsoft.EntityFrameworkCore.SqlServer` (likely a residue from scaffolding, though SQLite is still primary).
    *   Added `Microsoft.VisualStudio.Web.CodeGeneration.Design` for scaffolding tools.
This enhances the application's functionality by providing a knowledge base and improves the user experience with a cleaner dashboard layout.
			
			
This commit is contained in:
		
							parent
							
								
									1f50fedb80
								
							
						
					
					
						commit
						5074a9664a
					
				
					 17 changed files with 689 additions and 18 deletions
				
			
		
							
								
								
									
										157
									
								
								Controllers/LawnCareTipController.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								Controllers/LawnCareTipController.cs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,157 @@ | |||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Threading.Tasks; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Microsoft.AspNetCore.Mvc.Rendering; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using turf_tasker.Data; | ||||
| using turf_tasker.Models; | ||||
| 
 | ||||
| namespace turf_tasker.Controllers | ||||
| { | ||||
|     public class LawnCareTipController : Controller | ||||
|     { | ||||
|         private readonly ApplicationDbContext _context; | ||||
| 
 | ||||
|         public LawnCareTipController(ApplicationDbContext context) | ||||
|         { | ||||
|             _context = context; | ||||
|         } | ||||
| 
 | ||||
|         // GET: LawnCareTip | ||||
|         public async Task<IActionResult> Index() | ||||
|         { | ||||
|             return View(await _context.LawnCareTips.ToListAsync()); | ||||
|         } | ||||
| 
 | ||||
|         // GET: LawnCareTip/Details/5 | ||||
|         public async Task<IActionResult> Details(int? id) | ||||
|         { | ||||
|             if (id == null) | ||||
|             { | ||||
|                 return NotFound(); | ||||
|             } | ||||
| 
 | ||||
|             var lawnCareTip = await _context.LawnCareTips | ||||
|                 .FirstOrDefaultAsync(m => m.Id == id); | ||||
|             if (lawnCareTip == null) | ||||
|             { | ||||
|                 return NotFound(); | ||||
|             } | ||||
| 
 | ||||
|             return View(lawnCareTip); | ||||
|         } | ||||
| 
 | ||||
|         // GET: LawnCareTip/Create | ||||
|         public IActionResult Create() | ||||
|         { | ||||
|             return View(); | ||||
|         } | ||||
| 
 | ||||
|         // POST: LawnCareTip/Create | ||||
|         // To protect from overposting attacks, enable the specific properties you want to bind to. | ||||
|         // For more details, see http://go.microsoft.com/fwlink/?LinkId=317598. | ||||
|         [HttpPost] | ||||
|         [ValidateAntiForgeryToken] | ||||
|         public async Task<IActionResult> Create([Bind("Id,Title,Category,Content")] LawnCareTip lawnCareTip) | ||||
|         { | ||||
|             if (ModelState.IsValid) | ||||
|             { | ||||
|                 _context.Add(lawnCareTip); | ||||
|                 await _context.SaveChangesAsync(); | ||||
|                 return RedirectToAction(nameof(Index)); | ||||
|             } | ||||
|             return View(lawnCareTip); | ||||
|         } | ||||
| 
 | ||||
|         // GET: LawnCareTip/Edit/5 | ||||
|         public async Task<IActionResult> Edit(int? id) | ||||
|         { | ||||
|             if (id == null) | ||||
|             { | ||||
|                 return NotFound(); | ||||
|             } | ||||
| 
 | ||||
|             var lawnCareTip = await _context.LawnCareTips.FindAsync(id); | ||||
|             if (lawnCareTip == null) | ||||
|             { | ||||
|                 return NotFound(); | ||||
|             } | ||||
|             return View(lawnCareTip); | ||||
|         } | ||||
| 
 | ||||
|         // POST: LawnCareTip/Edit/5 | ||||
|         // To protect from overposting attacks, enable the specific properties you want to bind to. | ||||
|         // For more details, see http://go.microsoft.com/fwlink/?LinkId=317598. | ||||
|         [HttpPost] | ||||
|         [ValidateAntiForgeryToken] | ||||
|         public async Task<IActionResult> Edit(int id, [Bind("Id,Title,Category,Content")] LawnCareTip lawnCareTip) | ||||
|         { | ||||
|             if (id != lawnCareTip.Id) | ||||
|             { | ||||
|                 return NotFound(); | ||||
|             } | ||||
| 
 | ||||
|             if (ModelState.IsValid) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     _context.Update(lawnCareTip); | ||||
|                     await _context.SaveChangesAsync(); | ||||
|                 } | ||||
|                 catch (DbUpdateConcurrencyException) | ||||
|                 { | ||||
|                     if (!LawnCareTipExists(lawnCareTip.Id)) | ||||
|                     { | ||||
|                         return NotFound(); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         throw; | ||||
|                     } | ||||
|                 } | ||||
|                 return RedirectToAction(nameof(Index)); | ||||
|             } | ||||
|             return View(lawnCareTip); | ||||
|         } | ||||
| 
 | ||||
|         // GET: LawnCareTip/Delete/5 | ||||
|         public async Task<IActionResult> Delete(int? id) | ||||
|         { | ||||
|             if (id == null) | ||||
|             { | ||||
|                 return NotFound(); | ||||
|             } | ||||
| 
 | ||||
|             var lawnCareTip = await _context.LawnCareTips | ||||
|                 .FirstOrDefaultAsync(m => m.Id == id); | ||||
|             if (lawnCareTip == null) | ||||
|             { | ||||
|                 return NotFound(); | ||||
|             } | ||||
| 
 | ||||
|             return View(lawnCareTip); | ||||
|         } | ||||
| 
 | ||||
|         // POST: LawnCareTip/Delete/5 | ||||
|         [HttpPost, ActionName("Delete")] | ||||
|         [ValidateAntiForgeryToken] | ||||
|         public async Task<IActionResult> DeleteConfirmed(int id) | ||||
|         { | ||||
|             var lawnCareTip = await _context.LawnCareTips.FindAsync(id); | ||||
|             if (lawnCareTip != null) | ||||
|             { | ||||
|                 _context.LawnCareTips.Remove(lawnCareTip); | ||||
|             } | ||||
| 
 | ||||
|             await _context.SaveChangesAsync(); | ||||
|             return RedirectToAction(nameof(Index)); | ||||
|         } | ||||
| 
 | ||||
|         private bool LawnCareTipExists(int id) | ||||
|         { | ||||
|             return _context.LawnCareTips.Any(e => e.Id == id); | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Blake Ridgway
						Blake Ridgway