ce76046a29
- 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
73 lines
2.9 KiB
C#
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;
|
|
}
|