128 lines
5.1 KiB
C#
128 lines
5.1 KiB
C#
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using JobTrackerApi.Data;
|
|
using JobTrackerApi.Models;
|
|
using System.Security.Claims;
|
|
|
|
namespace JobTrackerApi.Controllers
|
|
{
|
|
[ApiController]
|
|
[Route("api/companies")]
|
|
public class CompaniesController : ControllerBase
|
|
{
|
|
private readonly JobTrackerContext _db;
|
|
|
|
public CompaniesController(JobTrackerContext db)
|
|
{
|
|
_db = db;
|
|
}
|
|
|
|
private string? CurrentUserId =>
|
|
User?.FindFirstValue(ClaimTypes.NameIdentifier) ?? User?.FindFirstValue("sub");
|
|
|
|
[HttpGet]
|
|
public async Task<ActionResult<List<Company>>> GetAll(CancellationToken cancellationToken)
|
|
{
|
|
var userId = CurrentUserId;
|
|
var q = _db.Companies.AsQueryable();
|
|
if (!string.IsNullOrWhiteSpace(userId))
|
|
q = q.Where(c => c.OwnerUserId == userId);
|
|
|
|
var companies = await q
|
|
.OrderBy(c => c.Name)
|
|
.ToListAsync(cancellationToken);
|
|
|
|
return Ok(companies);
|
|
}
|
|
|
|
[HttpGet("{id:int}")]
|
|
public async Task<ActionResult<Company>> GetById([FromRoute] int id, CancellationToken cancellationToken)
|
|
{
|
|
var userId = CurrentUserId;
|
|
var q = _db.Companies.AsQueryable();
|
|
if (!string.IsNullOrWhiteSpace(userId))
|
|
q = q.Where(c => c.OwnerUserId == userId);
|
|
|
|
var company = await q.FirstOrDefaultAsync(c => c.Id == id, cancellationToken);
|
|
if (company is null) return NotFound();
|
|
return Ok(company);
|
|
}
|
|
|
|
public sealed record CreateCompanyRequest(string Name, string? Location, string? Source);
|
|
public sealed record UpdateCompanyRequest(
|
|
string Name,
|
|
string? Location,
|
|
string? Source,
|
|
string? RecruiterName,
|
|
string? RecruiterEmail,
|
|
string? RecruiterLinkedIn,
|
|
DateTime? LastContactedAt,
|
|
DateTime? NextContactAt,
|
|
string? PipelineStage
|
|
);
|
|
|
|
[HttpPost]
|
|
public async Task<ActionResult<Company>> Create([FromBody] CreateCompanyRequest request, CancellationToken cancellationToken)
|
|
{
|
|
var userId = CurrentUserId;
|
|
var name = (request.Name ?? "").Trim();
|
|
if (name.Length == 0) return BadRequest("Company name is required.");
|
|
|
|
var existingQuery = _db.Companies.AsQueryable();
|
|
if (!string.IsNullOrWhiteSpace(userId))
|
|
existingQuery = existingQuery.Where(c => c.OwnerUserId == userId);
|
|
|
|
var existing = await existingQuery
|
|
.FirstOrDefaultAsync(c => c.Name.ToLower() == name.ToLower(), cancellationToken);
|
|
|
|
if (existing is not null)
|
|
{
|
|
// Idempotent create: return existing instead of failing.
|
|
return Ok(existing);
|
|
}
|
|
|
|
var company = new Company
|
|
{
|
|
OwnerUserId = string.IsNullOrWhiteSpace(userId) ? null : userId,
|
|
Name = name,
|
|
Location = string.IsNullOrWhiteSpace(request.Location) ? null : request.Location.Trim(),
|
|
Source = string.IsNullOrWhiteSpace(request.Source) ? null : request.Source.Trim(),
|
|
};
|
|
|
|
_db.Companies.Add(company);
|
|
await _db.SaveChangesAsync(cancellationToken);
|
|
|
|
return CreatedAtAction(nameof(GetById), new { id = company.Id }, company);
|
|
}
|
|
|
|
[HttpPut("{id:int}")]
|
|
public async Task<ActionResult<Company>> Update([FromRoute] int id, [FromBody] UpdateCompanyRequest request, CancellationToken cancellationToken)
|
|
{
|
|
var userId = CurrentUserId;
|
|
var q = _db.Companies.AsQueryable();
|
|
if (!string.IsNullOrWhiteSpace(userId))
|
|
q = q.Where(c => c.OwnerUserId == userId);
|
|
|
|
var company = await q.FirstOrDefaultAsync(c => c.Id == id, cancellationToken);
|
|
if (company is null) return NotFound();
|
|
|
|
var name = (request.Name ?? "").Trim();
|
|
if (name.Length == 0) return BadRequest("Company name is required.");
|
|
|
|
company.Name = name;
|
|
company.Location = string.IsNullOrWhiteSpace(request.Location) ? null : request.Location.Trim();
|
|
company.Source = string.IsNullOrWhiteSpace(request.Source) ? null : request.Source.Trim();
|
|
|
|
company.RecruiterName = string.IsNullOrWhiteSpace(request.RecruiterName) ? null : request.RecruiterName.Trim();
|
|
company.RecruiterEmail = string.IsNullOrWhiteSpace(request.RecruiterEmail) ? null : request.RecruiterEmail.Trim();
|
|
company.RecruiterLinkedIn = string.IsNullOrWhiteSpace(request.RecruiterLinkedIn) ? null : request.RecruiterLinkedIn.Trim();
|
|
company.PipelineStage = string.IsNullOrWhiteSpace(request.PipelineStage) ? null : request.PipelineStage.Trim();
|
|
company.LastContactedAt = request.LastContactedAt;
|
|
company.NextContactAt = request.NextContactAt;
|
|
|
|
await _db.SaveChangesAsync(cancellationToken);
|
|
return Ok(company);
|
|
}
|
|
}
|
|
}
|