277 lines
12 KiB
Plaintext
277 lines
12 KiB
Plaintext
@model WriterDashboardViewModel
|
|
@{
|
|
ViewData["Title"] = "Writer Workspace";
|
|
var message = TempData["WriterWorkspaceMessage"] as string;
|
|
var error = TempData["WriterWorkspaceError"] as string;
|
|
}
|
|
|
|
<div class="page-heading writer-dashboard-heading">
|
|
<div>
|
|
<p class="eyebrow">Today view</p>
|
|
<h1>Writer Workspace <help-icon key="workspace.overview" /></h1>
|
|
<p class="lead-text">A practical control room for drafting, revision, polish, and story readiness.</p>
|
|
</div>
|
|
<div class="button-row">
|
|
<a class="btn btn-outline-primary" asp-action="WritingPlans">Writing Plans</a>
|
|
<a class="btn btn-outline-primary" asp-action="ScheduleSetup" asp-route-projectId="@Model.ProjectID">Schedule Setup</a>
|
|
<a class="btn btn-outline-secondary" asp-action="SchedulePreview">Schedule Preview</a>
|
|
<form asp-action="Index" method="get" class="story-bible-search">
|
|
<select class="form-select" name="projectId" asp-items="Model.ProjectOptions">
|
|
<option value="">All projects</option>
|
|
</select>
|
|
<button class="btn btn-primary" type="submit">Focus</button>
|
|
</form>
|
|
</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.WritingSchedule.RebalancePlanCount > 0)
|
|
{
|
|
<div class="alert alert-info">
|
|
You have @Model.WritingSchedule.RebalancePlanCount writing schedule(s) that may need rebalancing.
|
|
<a asp-action="SchedulePreview">Review Schedules</a>
|
|
</div>
|
|
}
|
|
|
|
<section class="story-bible-section">
|
|
<div class="story-bible-section-heading">
|
|
<div>
|
|
<p class="eyebrow">Daily plan</p>
|
|
<h2>Today's Writing</h2>
|
|
</div>
|
|
<span class="soft-count">@Model.WritingSchedule.TodayTasks.Count tasks</span>
|
|
</div>
|
|
|
|
@if (!Model.WritingSchedule.HasActivePlans)
|
|
{
|
|
<p class="muted">No writing schedule configured.</p>
|
|
<a class="btn btn-primary" asp-action="ScheduleSetup" asp-route-projectId="@Model.ProjectID">Create Writing Schedule</a>
|
|
}
|
|
else
|
|
{
|
|
@if (!Model.WritingSchedule.TodayTasks.Any())
|
|
{
|
|
<p class="muted">No writing tasks scheduled for today.</p>
|
|
}
|
|
else
|
|
{
|
|
<div class="table-responsive">
|
|
<table class="table align-middle">
|
|
<thead>
|
|
<tr>
|
|
<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>Blocked</th>
|
|
<th>Writing Plan</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach (var item in Model.WritingSchedule.TodayTasks)
|
|
{
|
|
<tr>
|
|
<td>@item.TaskType</td>
|
|
<td>@item.BookDisplayTitle</td>
|
|
<td>Chapter @item.ChapterNumber: @item.ChapterTitle</td>
|
|
<td>
|
|
<a asp-controller="Scenes" asp-action="Edit" asp-route-id="@item.SceneID">
|
|
Scene @item.SceneNumber: @item.SceneTitle
|
|
</a>
|
|
<div class="small">
|
|
<a asp-controller="Exports" asp-action="WritingSession" asp-route-sceneId="@item.SceneID">Writing Guide</a>
|
|
</div>
|
|
</td>
|
|
<td>@(item.Priority?.ToString() ?? "-")</td>
|
|
<td>@(item.EstimatedMinutes?.ToString() ?? "-")</td>
|
|
<td>@(item.TargetWords?.ToString() ?? "-")</td>
|
|
<td>@(item.IsBlocked ? "Yes" : "No")</td>
|
|
<td>@item.PlanName</td>
|
|
<td>
|
|
<div class="button-row">
|
|
<form asp-action="MarkScheduleItemComplete" method="post">
|
|
<input type="hidden" name="writingScheduleItemId" value="@item.WritingScheduleItemID" />
|
|
<input type="hidden" name="projectId" value="@Model.ProjectID" />
|
|
<button class="btn btn-sm btn-primary" type="submit">Mark Complete</button>
|
|
</form>
|
|
<form asp-action="SkipScheduleItem" method="post">
|
|
<input type="hidden" name="writingScheduleItemId" value="@item.WritingScheduleItemID" />
|
|
<input type="hidden" name="projectId" value="@Model.ProjectID" />
|
|
<button class="btn btn-sm btn-outline-secondary" type="submit">Skip</button>
|
|
</form>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
}
|
|
|
|
<div class="story-bible-section-heading mt-4">
|
|
<div>
|
|
<p class="eyebrow">Upcoming work</p>
|
|
<h2>Coming Up</h2>
|
|
</div>
|
|
<span class="soft-count">@Model.WritingSchedule.UpcomingTasks.Count tasks</span>
|
|
</div>
|
|
|
|
@if (!Model.WritingSchedule.UpcomingTasks.Any())
|
|
{
|
|
<p class="muted">No upcoming writing tasks.</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>Estimated Minutes</th>
|
|
<th>Target Words</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach (var item in Model.WritingSchedule.UpcomingTasks)
|
|
{
|
|
<tr>
|
|
<td>@item.ScheduledDate.ToString("dd MMM yyyy")</td>
|
|
<td>@item.TaskType</td>
|
|
<td>@item.BookDisplayTitle</td>
|
|
<td>Chapter @item.ChapterNumber: @item.ChapterTitle</td>
|
|
<td>
|
|
<a asp-controller="Scenes" asp-action="Edit" asp-route-id="@item.SceneID">
|
|
Scene @item.SceneNumber: @item.SceneTitle
|
|
</a>
|
|
</td>
|
|
<td>@(item.EstimatedMinutes?.ToString() ?? "-")</td>
|
|
<td>@(item.TargetWords?.ToString() ?? "-")</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
}
|
|
|
|
<div class="story-bible-section-heading mt-4">
|
|
<div>
|
|
<p class="eyebrow">Schedule</p>
|
|
<h2>Progress Summary</h2>
|
|
</div>
|
|
</div>
|
|
|
|
@if (!Model.WritingSchedule.HasActiveSchedule)
|
|
{
|
|
<p class="muted">No active schedule</p>
|
|
}
|
|
|
|
<div class="story-bible-grid story-bible-grid-compact">
|
|
<article class="story-bible-card"><h3>Active Plans</h3><strong class="writer-kpi">@Model.WritingSchedule.ActivePlanCount</strong></article>
|
|
<article class="story-bible-card"><h3>Total Planned Tasks</h3><strong class="writer-kpi">@Model.WritingSchedule.TotalPlannedTasks</strong></article>
|
|
<article class="story-bible-card"><h3>Completed Tasks</h3><strong class="writer-kpi">@Model.WritingSchedule.CompletedTasks</strong></article>
|
|
<article class="story-bible-card"><h3>Skipped Tasks</h3><strong class="writer-kpi">@Model.WritingSchedule.SkippedTasks</strong></article>
|
|
<article class="story-bible-card"><h3>Remaining Tasks</h3><strong class="writer-kpi">@Model.WritingSchedule.RemainingTasks</strong></article>
|
|
<article class="story-bible-card"><h3>Projected Finish Date</h3><strong class="writer-kpi">@(Model.WritingSchedule.ProjectedFinishDate?.ToString("dd MMM yyyy") ?? "-")</strong></article>
|
|
</div>
|
|
}
|
|
</section>
|
|
|
|
<div class="writer-dashboard-grid">
|
|
<section class="writer-dashboard-panel">
|
|
<div class="story-bible-section-heading">
|
|
<div>
|
|
<p class="eyebrow">Write Next</p>
|
|
<h2>Write Next <help-icon key="workspace.writeNext" /></h2>
|
|
</div>
|
|
<span class="soft-count">@Model.WriteNext.Count scenes</span>
|
|
</div>
|
|
<partial name="_WriterSceneQueue" model="Model.WriteNext" />
|
|
</section>
|
|
|
|
<section class="writer-dashboard-panel">
|
|
<div class="story-bible-section-heading">
|
|
<div>
|
|
<p class="eyebrow">In progress</p>
|
|
<h2>Continue Writing <help-icon key="workspace.writeNext" /></h2>
|
|
</div>
|
|
<span class="soft-count">@Model.ContinueWriting.Count scenes</span>
|
|
</div>
|
|
<partial name="_WriterSceneQueue" model="Model.ContinueWriting" />
|
|
</section>
|
|
|
|
<section class="writer-dashboard-panel">
|
|
<div class="story-bible-section-heading">
|
|
<div>
|
|
<p class="eyebrow">Revision</p>
|
|
<h2>Revision Queue <help-icon key="workspace.revisionQueue" /></h2>
|
|
</div>
|
|
<span class="soft-count">@Model.RevisionQueue.Count scenes</span>
|
|
</div>
|
|
<partial name="_WriterSceneQueue" model="Model.RevisionQueue" />
|
|
</section>
|
|
|
|
<section class="writer-dashboard-panel">
|
|
<div class="story-bible-section-heading">
|
|
<div>
|
|
<p class="eyebrow">Final pass</p>
|
|
<h2>Polishing Queue <help-icon key="workspace.polishingQueue" /></h2>
|
|
</div>
|
|
<span class="soft-count">@Model.PolishingQueue.Count scenes</span>
|
|
</div>
|
|
<partial name="_WriterSceneQueue" model="Model.PolishingQueue" />
|
|
</section>
|
|
</div>
|
|
|
|
<section class="story-bible-section">
|
|
<div class="story-bible-section-heading">
|
|
<div>
|
|
<p class="eyebrow">Story health</p>
|
|
<h2>Reminders <help-icon key="workspace.reminders" /></h2>
|
|
</div>
|
|
<span class="soft-count">@Model.StoryHealthReminders.Count items</span>
|
|
</div>
|
|
<div class="attention-list">
|
|
@foreach (var reminder in Model.StoryHealthReminders)
|
|
{
|
|
<article>
|
|
<span class="badge text-bg-light">@reminder.Category</span>
|
|
@if (reminder.SceneID.HasValue)
|
|
{
|
|
<strong>
|
|
<a asp-controller="Scenes" asp-action="Edit" asp-route-id="@reminder.SceneID">@reminder.Title</a>
|
|
</strong>
|
|
}
|
|
else
|
|
{
|
|
<strong>@reminder.Title</strong>
|
|
}
|
|
@if (!string.IsNullOrWhiteSpace(reminder.Detail))
|
|
{
|
|
<p>@reminder.Detail</p>
|
|
}
|
|
@if (reminder.SceneID.HasValue)
|
|
{
|
|
<a asp-controller="Scenes" asp-action="Edit" asp-route-id="@reminder.SceneID">Open scene</a>
|
|
}
|
|
</article>
|
|
}
|
|
</div>
|
|
</section>
|