Files
jobtrackingapp/JobTrackerApi/Models/InterviewPrepItem.cs
T
cesnimda ce76046a29 feat: complete release readiness work
- consolidate API ownership and remove dead vendor code

- add Stripe billing, learning paths, and public CV hardening

- add migration, recovery, security, audit, and browser gates
2026-07-31 16:54:16 +02:00

73 lines
2.9 KiB
C#

namespace JobTrackerApi.Models;
// Phase 5.5 — Interview preparation the USER owns.
//
// Distinct from InterviewPrepNote and AiWorkspaceNote, which are AI caches: both are regenerated when
// their context changes, so anything a user typed there would eventually be overwritten. This is the
// durable side — company research, technical notes, behavioural answers, STAR examples and the user's
// own questions — and nothing regenerates it.
//
// One table for every category rather than a table per category: they differ only by label, and a new
// category must not need a migration. Reconciler-owned
// (docs/infrastructure/database-ownership.md); its migration is a no-op.
public sealed class InterviewPrepItem
{
public int Id { get; set; }
public string OwnerUserId { get; set; } = string.Empty;
public int JobApplicationId { get; set; }
public JobApplication? JobApplication { get; set; }
// company-research | technical | behavioural | star | question | note
public string Category { get; set; } = InterviewPrepCategories.Note;
// The prompt side: a question to answer, or the heading of a research note.
public string Title { get; set; } = string.Empty;
// The user's own words. Always theirs to edit — an AI suggestion only lands here once saved.
public string? Content { get; set; }
// user | ai — whether the user wrote this or accepted it from a suggestion. Recorded for honesty
// in the UI, not to restrict editing: an accepted suggestion is fully editable afterwards.
public string Source { get; set; } = InterviewPrepSources.User;
// Practice tracking, so the section doubles as the preparation checklist.
public bool IsPrepared { get; set; }
public int SortOrder { get; set; }
public DateTimeOffset CreatedAtUtc { get; set; } = DateTimeOffset.UtcNow;
public DateTimeOffset UpdatedAtUtc { get; set; } = DateTimeOffset.UtcNow;
}
public static class InterviewPrepCategories
{
public const string CompanyResearch = "company-research";
public const string Technical = "technical";
public const string Behavioural = "behavioural";
public const string Star = "star";
public const string Question = "question";
public const string Note = "note";
// Display order in the workspace: understand the company, then the role, then yourself, then what
// you want to ask them.
public static readonly string[] Order =
{
CompanyResearch, Technical, Behavioural, Star, Question, Note,
};
public static int Rank(string? category)
{
var i = Array.IndexOf(Order, category ?? Note);
return i < 0 ? Order.Length : i;
}
public static bool IsValid(string? value) => Array.IndexOf(Order, value ?? string.Empty) >= 0;
}
public static class InterviewPrepSources
{
public const string User = "user";
public const string Ai = "ai";
public static bool IsValid(string? value) => value is User or Ai;
}