First Commit
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user