feat(jobs): complete workspace draft parity
CI and Deploy / test (pull_request) Successful in 5m4s
CI and Deploy / deploy (pull_request) Has been skipped

This commit is contained in:
cesnimda
2026-08-15 17:34:32 +02:00
parent 3b86ea2da0
commit deed948183
28 changed files with 676 additions and 131 deletions
@@ -218,7 +218,11 @@ namespace JobTrackerApi.Controllers
TailoredCvRenderOptions? RenderOptions,
string? Status);
public sealed record GenerateApplicationPackageDto(string TailoredCvText, string? CoverLetterDraft, string? ApplicationAnswerDraft, string? RecruiterMessageDraft, List<string> KeyPoints, List<string> AttachmentSignals, List<string> AttachmentFilesUsed, List<string> CoverLetterVariants, List<string> RecruiterMessageVariants);
public sealed record SaveApplicationDraftsRequest(string? CoverLetterText, string? Notes, string? RecruiterMessageDraft);
public sealed record SaveApplicationDraftsRequest(
string? CoverLetterText,
string? Notes,
string? RecruiterMessageDraft,
string? ApplicationAnswerDraft = null);
public sealed record SavedPackageMaterial(string? TailoredCvText, string? CoverLetterText, string? RecruiterMessageDraft, string? Notes);
public sealed record InterviewPrepDto(string Summary, List<string> TalkingPoints, List<string> LikelyQuestions, List<string> WeakSpots);
public sealed record ReadinessDto(int Score, string Level, List<string> Completed, List<string> Missing, List<string> Reminders, WorkflowSignalDto WorkflowSignal);
@@ -837,7 +837,11 @@ Canonical profile:
job.FeedbackRequestedAt = request.FeedbackRequestedAt;
// HasResume/HasCoverLetter/HasPortfolio/HasOtherAttachment are derived from
// Attachment rows, not settable here -- see AttachmentsController.RecomputeAttachmentFlagsAsync.
job.Notes = request.Notes;
// Application answers use the legacy Notes column for storage compatibility, but the
// general editor owns only human notes. Preserve the separate answer when those notes
// are edited; the application-package endpoint is the only place that clears it.
var savedApplicationAnswer = ExtractSavedApplicationAnswerDraft(job.Notes);
job.Notes = UpsertSavedApplicationAnswerDraft(request.Notes, savedApplicationAnswer);
job.Description = request.Description;
job.TranslatedDescription = request.TranslatedDescription;
job.DescriptionLanguage = request.DescriptionLanguage;
@@ -1826,19 +1830,26 @@ Candidate CV/profile:
var job = await _db.JobApplications.FirstOrDefaultAsync(j => j.Id == id, cancellationToken);
if (job is null) return NotFound();
if (!string.IsNullOrWhiteSpace(request.CoverLetterText))
if (request.CoverLetterText is not null)
{
job.CoverLetterText = request.CoverLetterText.Trim();
job.CoverLetterText = string.IsNullOrWhiteSpace(request.CoverLetterText) ? null : request.CoverLetterText.Trim();
}
if (!string.IsNullOrWhiteSpace(request.Notes))
if (request.Notes is not null)
{
job.Notes = request.Notes.Trim();
job.Notes = string.IsNullOrWhiteSpace(request.Notes) ? null : request.Notes.Trim();
}
if (!string.IsNullOrWhiteSpace(request.RecruiterMessageDraft))
if (request.ApplicationAnswerDraft is not null)
{
job.RecruiterMessageDraft = request.RecruiterMessageDraft.Trim();
job.Notes = UpsertSavedApplicationAnswerDraft(job.Notes, request.ApplicationAnswerDraft);
}
if (request.RecruiterMessageDraft is not null)
{
job.RecruiterMessageDraft = string.IsNullOrWhiteSpace(request.RecruiterMessageDraft)
? null
: request.RecruiterMessageDraft.Trim();
}
await _db.SaveChangesAsync(cancellationToken);