Newer
Older
job-tracker / src / main / java / com / kpaudel / controller / ApiController.java
package com.kpaudel.controller;

import com.kpaudel.model.ApplicationStatus;
import com.kpaudel.model.Company;
import com.kpaudel.model.JobApplication;
import com.kpaudel.repository.CompanyRepository;
import com.kpaudel.repository.JobApplicationRepository;
import com.kpaudel.service.JobService;
import com.opencsv.CSVWriter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ContentDisposition;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "http://localhost:3000")  // frontend dev CORS
public class ApiController {
    private final JobService service;
    private final CompanyRepository companyRepo;
    private final JobApplicationRepository jobRepo;

    public ApiController(JobService service, CompanyRepository companyRepo, JobApplicationRepository jobRepo) {
        this.service = service;
        this.companyRepo = companyRepo;
        this.jobRepo = jobRepo;
    }

    @GetMapping("/jobs")
    public List<JobApplication> listJobs(@RequestParam Optional<ApplicationStatus> status) {
        return status.map(jobRepo::findByStatus).orElse(jobRepo.findAll());
    }

    @GetMapping("/jobs/{id}")
    public ResponseEntity<JobApplication> getJob(@PathVariable UUID id) {
        return this.jobRepo.findById(id).map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }

    @PostMapping("/jobs")
    public JobApplication createJob(@RequestBody JobApplication job) {
        return this.service.create(job.getCompany().getId(), job);
    }

    @PutMapping("/jobs/{id}")
    public ResponseEntity<JobApplication> updateJob(@PathVariable UUID id, @RequestBody JobApplication updated) {
        return jobRepo.findById(id)
                .map(existing -> {
                    updated.setId(id);
                    return ResponseEntity.ok(jobRepo.save(updated));
                })
                .orElse(ResponseEntity.notFound().build());
    }

    @PatchMapping("/jobs/{id}/status")
    public JobApplication updateStatus(@PathVariable UUID id, @RequestBody Map<String, String> body) {
        ApplicationStatus status = ApplicationStatus.valueOf(body.get("status"));
        return service.updateStatus(id, status);
    }

    @DeleteMapping("/jobs/{id}")
    public ResponseEntity<Void> deleteJob(@PathVariable UUID id) {
        if (jobRepo.existsById(id)) {
            jobRepo.deleteById(id);
            return ResponseEntity.noContent().build();
        }
        return ResponseEntity.notFound().build();
    }

    @GetMapping("/companies")
    public List<Company> listCompanies() {
        return this.companyRepo.findAll();
    }

    @GetMapping("/companies/{id}")
    public ResponseEntity<Company> getCompany(@PathVariable UUID id) {
        return companyRepo.findById(id)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }

    @GetMapping("/companies/{id}/jobs")
    public List<JobApplication> listJobsByCompany(@PathVariable UUID id) {
        return jobRepo.findByCompanyId(id);
    }

    @PostMapping("/companies")
    public Company createCompany(@RequestBody Company company) {
        return this.companyRepo.save(company);
    }


    @PutMapping("/companies/{id}")
    public ResponseEntity<Company> updateCompany(@PathVariable UUID id, @RequestBody Company updated) {
        return companyRepo.findById(id)
                .map(existing -> {
                    updated.setId(id);
                    return ResponseEntity.ok(companyRepo.save(updated));
                })
                .orElse(ResponseEntity.notFound().build());
    }

    @DeleteMapping("/companies/{id}")
    public ResponseEntity<Void> deleteCompany(@PathVariable UUID id) {
        if (companyRepo.existsById(id)) {
            companyRepo.deleteById(id);
            return ResponseEntity.noContent().build();
        }
        return ResponseEntity.notFound().build();
    }

    @GetMapping("/jobs/export")
    public ResponseEntity<byte[]> exportJobs() throws IOException {
        List<JobApplication> jobs = this.jobRepo.findAll();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        CSVWriter writer = new CSVWriter(new java.io.OutputStreamWriter(out));
        //Add headers
        writer.writeNext(new String[]{"ID", "Role", "Company","JobUrl", "Applied Date", "Source", "Salary Expectation","Status", "Location", "Last Updated", "Notes"});
        //Add Data
        for (JobApplication job : jobs) {
            writer.writeNext(new String[]{
                    job.getId().toString(),
                    job.getRole(),
                    job.getCompany().getName(),
                    job.getJobUrl(),
                    job.getAppliedDate().toString(),
                    job.getSource(),
                    job.getSalaryExpectation(),
                    job.getStatus().name(),
                    job.getLocation(),
                    job.getLastUpdated().toString(),
                    job.getNotes()
            });
        }
        writer.close();
        byte[] data = out.toByteArray();
        String timestamp = java.time.LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType("text/csv"));
        headers.setContentDisposition(ContentDisposition.attachment().filename("jobs_" + timestamp + ".csv").build());

        return new ResponseEntity<>(data, headers, HttpStatus.OK);
    }
    @GetMapping("/companies/export")
    public ResponseEntity<byte[]> exportCompanies() throws IOException {
        List<Company> companies = this.companyRepo.findAll();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        CSVWriter writer = new CSVWriter(new java.io.OutputStreamWriter(out));
        //Add headers
        writer.writeNext(new String[]{"ID", "Name", "Website", "Notes"});
        //Add Data
        for (Company company : companies) {
            writer.writeNext(new String[]{
                    company.getId().toString(),
                    company.getName(),
                    company.getWebsite(),
                    company.getNotes()
            });
        }
        writer.close();
        byte[] data = out.toByteArray();
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType("text/csv"));
        headers.setContentDisposition(ContentDisposition.attachment().filename("companies_" + timestamp + ".csv").build());

        return new ResponseEntity<>(data, headers, HttpStatus.OK);
    }
}