268 lines
12 KiB
Plaintext
268 lines
12 KiB
Plaintext
@model WritingSchedulePreviewViewModel
|
|
@{
|
|
ViewData["Title"] = "Schedule Preview";
|
|
var message = TempData["SchedulePreviewMessage"] as string;
|
|
var error = TempData["SchedulePreviewError"] as string;
|
|
}
|
|
|
|
<nav class="breadcrumb-trail" aria-label="Breadcrumb">
|
|
<a asp-controller="Writer" asp-action="Index">Writer Workspace</a>
|
|
<span>Schedule Preview</span>
|
|
</nav>
|
|
|
|
<div class="page-heading compact">
|
|
<div>
|
|
<p class="eyebrow">Validation</p>
|
|
<h1>Schedule Preview</h1>
|
|
<p class="lead-text">Generated writing schedule items.</p>
|
|
</div>
|
|
</div>
|
|
|
|
@if (!string.IsNullOrWhiteSpace(message))
|
|
{
|
|
<div class="alert alert-info">@message</div>
|
|
}
|
|
|
|
@if (!string.IsNullOrWhiteSpace(error))
|
|
{
|
|
<div class="alert alert-warning">@error</div>
|
|
}
|
|
|
|
@if (!Model.Plans.Any())
|
|
{
|
|
<section class="story-bible-section">
|
|
<p class="muted">No writing plans found.</p>
|
|
</section>
|
|
}
|
|
else
|
|
{
|
|
<section class="story-bible-section">
|
|
<div class="story-bible-section-heading">
|
|
<div>
|
|
<p class="eyebrow">Plan</p>
|
|
<h2>Writing Plan Selection</h2>
|
|
</div>
|
|
</div>
|
|
|
|
<form asp-action="SchedulePreview" method="get" class="story-bible-search mb-3">
|
|
<select class="form-select" name="writingPlanId">
|
|
@foreach (var plan in Model.Plans)
|
|
{
|
|
<option value="@plan.WritingPlanID" selected="@(plan.WritingPlanID == Model.SelectedWritingPlanID)">
|
|
@plan.PlanName - @plan.ProjectName / @(plan.BookTitle ?? "All Books") - @plan.DeadlineDate.ToString("dd MMM yyyy") - @(plan.IsActive ? "Active" : "Inactive")
|
|
</option>
|
|
}
|
|
</select>
|
|
<button class="btn btn-primary" type="submit">Select</button>
|
|
</form>
|
|
|
|
<div class="table-responsive">
|
|
<table class="table align-middle">
|
|
<thead>
|
|
<tr>
|
|
<th>Plan Name</th>
|
|
<th>Project</th>
|
|
<th>Book</th>
|
|
<th>Deadline Date</th>
|
|
<th>Active</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach (var plan in Model.Plans)
|
|
{
|
|
<tr>
|
|
<td>@plan.PlanName</td>
|
|
<td>@plan.ProjectName</td>
|
|
<td>@(plan.BookTitle ?? "All Books")</td>
|
|
<td>@plan.DeadlineDate.ToString("dd MMM yyyy")</td>
|
|
<td>@(plan.IsActive ? "Yes" : "No")</td>
|
|
<td>
|
|
@if (plan.WritingPlanID == Model.SelectedWritingPlanID)
|
|
{
|
|
<span class="status-pill">Selected</span>
|
|
}
|
|
else
|
|
{
|
|
<a asp-action="SchedulePreview" asp-route-writingPlanId="@plan.WritingPlanID">Select</a>
|
|
}
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
|
|
@if (Model.SelectedPlan is not null)
|
|
{
|
|
@if (Model.SelectedPlanRequiresRebalance)
|
|
{
|
|
<div class="alert alert-warning">Schedule requires attention.</div>
|
|
}
|
|
|
|
<section class="story-bible-section">
|
|
<div class="button-row">
|
|
<form asp-action="GenerateSchedule" method="post">
|
|
<input type="hidden" name="writingPlanId" value="@Model.SelectedPlan.WritingPlanID" />
|
|
<button class="btn btn-primary" type="submit">Generate Schedule</button>
|
|
</form>
|
|
<button class="btn btn-outline-danger" type="button" data-bs-toggle="modal" data-bs-target="#deleteGeneratedScheduleModal">Delete Generated Schedule</button>
|
|
@if (Model.SelectedPlanRequiresRebalance)
|
|
{
|
|
<a class="btn btn-outline-primary" asp-action="PreviewRebalance" asp-route-writingPlanId="@Model.SelectedPlan.WritingPlanID">Preview Rebalance</a>
|
|
}
|
|
</div>
|
|
</section>
|
|
|
|
<div class="modal fade" id="deleteGeneratedScheduleModal" tabindex="-1" aria-labelledby="deleteGeneratedScheduleModalTitle" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h2 class="modal-title fs-5" id="deleteGeneratedScheduleModalTitle">Delete generated schedule?</h2>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p>Delete generated schedule items for <strong>@Model.SelectedPlan.PlanName</strong>?</p>
|
|
<p class="muted mb-0">This removes the generated schedule items for this plan. The writing plan itself will remain.</p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
|
|
<form asp-action="DeleteGeneratedSchedule" method="post" class="m-0">
|
|
<input type="hidden" name="writingPlanId" value="@Model.SelectedPlan.WritingPlanID" />
|
|
<button class="btn btn-danger" type="submit">Delete</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@if (Model.RebalancePreview is not null)
|
|
{
|
|
<section class="story-bible-section">
|
|
<div class="story-bible-section-heading">
|
|
<div>
|
|
<p class="eyebrow">Rebalance</p>
|
|
<h2>Rebalance Preview</h2>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="story-bible-grid story-bible-grid-compact">
|
|
<article class="story-bible-card"><h3>Current Finish Date</h3><strong class="writer-kpi">@(Model.RebalancePreview.OriginalFinishDate?.ToString("dd MMM yyyy") ?? "-")</strong></article>
|
|
<article class="story-bible-card"><h3>Proposed Finish Date</h3><strong class="writer-kpi">@(Model.RebalancePreview.ProposedFinishDate?.ToString("dd MMM yyyy") ?? "-")</strong></article>
|
|
<article class="story-bible-card"><h3>Tasks Affected</h3><strong class="writer-kpi">@Model.RebalancePreview.TasksAffected</strong></article>
|
|
</div>
|
|
|
|
@if (!Model.RebalancePreview.Changes.Any())
|
|
{
|
|
<p class="muted">No planned tasks need new dates.</p>
|
|
}
|
|
else
|
|
{
|
|
<div class="table-responsive mt-3">
|
|
<table class="table align-middle">
|
|
<thead>
|
|
<tr>
|
|
<th>Task Type</th>
|
|
<th>Scene</th>
|
|
<th>Current Date</th>
|
|
<th>Proposed Date</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach (var change in Model.RebalancePreview.Changes)
|
|
{
|
|
<tr>
|
|
<td>@change.TaskType</td>
|
|
<td>@change.SceneName</td>
|
|
<td>@change.CurrentDate.ToString("dd MMM yyyy")</td>
|
|
<td>@change.ProposedDate.ToString("dd MMM yyyy")</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
}
|
|
|
|
<div class="button-row mt-3">
|
|
<form asp-action="ApplyRebalance" method="post">
|
|
<input type="hidden" name="writingPlanId" value="@Model.RebalancePreview.WritingPlanID" />
|
|
<button class="btn btn-primary" type="submit">Apply Rebalance</button>
|
|
</form>
|
|
<a class="btn btn-outline-secondary" asp-action="SchedulePreview" asp-route-writingPlanId="@Model.RebalancePreview.WritingPlanID">Cancel</a>
|
|
</div>
|
|
</section>
|
|
}
|
|
|
|
<section class="story-bible-section">
|
|
<div class="story-bible-section-heading">
|
|
<div>
|
|
<p class="eyebrow">Summary</p>
|
|
<h2>Schedule Summary</h2>
|
|
</div>
|
|
</div>
|
|
<div class="story-bible-grid story-bible-grid-compact">
|
|
<article class="story-bible-card"><h3>Total Tasks</h3><strong class="writer-kpi">@Model.TotalTasks</strong></article>
|
|
<article class="story-bible-card"><h3>Draft Tasks</h3><strong class="writer-kpi">@Model.DraftTasks</strong></article>
|
|
<article class="story-bible-card"><h3>Revision Tasks</h3><strong class="writer-kpi">@Model.RevisionTasks</strong></article>
|
|
<article class="story-bible-card"><h3>Polish Tasks</h3><strong class="writer-kpi">@Model.PolishTasks</strong></article>
|
|
<article class="story-bible-card"><h3>Total Estimated Minutes</h3><strong class="writer-kpi">@Model.TotalEstimatedMinutes</strong></article>
|
|
<article class="story-bible-card"><h3>Projected Finish Date</h3><strong class="writer-kpi">@(Model.ProjectedFinishDate?.ToString("dd MMM yyyy") ?? "-")</strong></article>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="story-bible-section">
|
|
<div class="story-bible-section-heading">
|
|
<div>
|
|
<p class="eyebrow">Items</p>
|
|
<h2>Schedule Preview Table</h2>
|
|
</div>
|
|
<span class="soft-count">@Model.Items.Count items</span>
|
|
</div>
|
|
|
|
@if (!Model.Items.Any())
|
|
{
|
|
<p class="muted">No schedule generated.</p>
|
|
}
|
|
else
|
|
{
|
|
<div class="table-responsive">
|
|
<table class="table align-middle">
|
|
<thead>
|
|
<tr>
|
|
<th>Scheduled Date</th>
|
|
<th>Task Type</th>
|
|
<th>Book</th>
|
|
<th>Chapter</th>
|
|
<th>Scene</th>
|
|
<th>Priority</th>
|
|
<th>Estimated Minutes</th>
|
|
<th>Target Words</th>
|
|
<th>Schedule Status</th>
|
|
<th>Blocked</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach (var item in Model.Items)
|
|
{
|
|
<tr>
|
|
<td>@item.ScheduledDate.ToString("dd MMM yyyy")</td>
|
|
<td>@item.TaskType</td>
|
|
<td>@item.BookTitle</td>
|
|
<td>Chapter @item.ChapterNumber: @item.ChapterTitle</td>
|
|
<td>Scene @item.SceneNumber: @item.SceneTitle</td>
|
|
<td>@(item.Priority?.ToString() ?? "-")</td>
|
|
<td>@(item.EstimatedMinutes?.ToString() ?? "-")</td>
|
|
<td>@(item.TargetWords?.ToString() ?? "-")</td>
|
|
<td>@item.ScheduleStatus</td>
|
|
<td>@(item.IsBlocked ? "Yes" : "No")</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
}
|
|
</section>
|
|
}
|
|
}
|