Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>annotationProcessor</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
Expand All @@ -108,6 +107,18 @@

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,33 @@
import org.example.projektarendehantering.presentation.dto.CaseDTO;
import org.springframework.stereotype.Component;

import java.util.stream.Collectors;

@Component
public class CaseMapper {

private final CaseNoteMapper caseNoteMapper;

public CaseMapper(CaseNoteMapper caseNoteMapper) {
this.caseNoteMapper = caseNoteMapper;
}

public CaseDTO toDTO(CaseEntity entity) {
if (entity == null) return null;
return new CaseDTO(
CaseDTO dto = new CaseDTO(
entity.getId(),
entity.getStatus(),
entity.getTitle(),
entity.getDescription(),
entity.getCreatedAt(),
entity.getPatient() != null ? entity.getPatient().getId() : null
);
if (entity.getNotes() != null) {
dto.setNotes(entity.getNotes().stream()
.map(caseNoteMapper::toDTO)
.collect(Collectors.toList()));
}
return dto;
}

public CaseEntity toEntity(CaseDTO dto) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.example.projektarendehantering.application.service;

import org.example.projektarendehantering.infrastructure.persistence.CaseNoteEntity;
import org.example.projektarendehantering.presentation.dto.CaseNoteDTO;
import org.springframework.stereotype.Component;

@Component
public class CaseNoteMapper {

public CaseNoteDTO toDTO(CaseNoteEntity entity) {
if (entity == null) return null;
return new CaseNoteDTO(
entity.getId(),
entity.getContent(),
entity.getAuthor(),
entity.getCreatedAt()
);
}

public CaseNoteEntity toEntity(CaseNoteDTO dto) {
if (dto == null) return null;
CaseNoteEntity entity = new CaseNoteEntity();
entity.setId(dto.getId());
entity.setContent(dto.getContent());
entity.setAuthor(dto.getAuthor());
entity.setCreatedAt(dto.getCreatedAt());
return entity;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import org.example.projektarendehantering.common.NotAuthorizedException;
import org.example.projektarendehantering.common.Role;
import org.example.projektarendehantering.infrastructure.persistence.CaseEntity;
import org.example.projektarendehantering.infrastructure.persistence.CaseNoteEntity;
import org.example.projektarendehantering.infrastructure.persistence.CaseNoteRepository;
import org.example.projektarendehantering.infrastructure.persistence.CaseRepository;
import org.example.projektarendehantering.infrastructure.persistence.EmployeeEntity;
import org.example.projektarendehantering.infrastructure.persistence.EmployeeRepository;
Expand All @@ -29,20 +31,31 @@ public class CaseService {
private final CaseRepository caseRepository;
private final CaseMapper caseMapper;
private final PatientRepository patientRepository;
private final CaseNoteRepository caseNoteRepository;
private final EmployeeRepository employeeRepository;

public CaseService(
CaseRepository caseRepository,
CaseMapper caseMapper,
PatientRepository patientRepository,
EmployeeRepository employeeRepository
) {
public CaseService(CaseRepository caseRepository, CaseMapper caseMapper, PatientRepository patientRepository, CaseNoteRepository caseNoteRepository, EmployeeRepository employeeRepository) {
this.caseRepository = caseRepository;
this.caseMapper = caseMapper;
this.patientRepository = patientRepository;
this.caseNoteRepository = caseNoteRepository;
this.employeeRepository = employeeRepository;
}

@Transactional
public void addNote(UUID caseId, String content, String author) {
CaseEntity caseEntity = caseRepository.findById(caseId)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Case not found"));

CaseNoteEntity note = new CaseNoteEntity();
note.setCaseEntity(caseEntity);
note.setContent(content);
note.setAuthor(author);
note.setCreatedAt(Instant.now());

caseNoteRepository.save(note);
}

@Transactional
public CaseDTO createCase(Actor actor, CaseDTO caseDTO) {
if (!canCreate(actor)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import jakarta.persistence.*;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Entity
Expand All @@ -23,16 +25,21 @@ public class CaseEntity {
@JoinColumn(name = "patient_id", nullable = true) // Optional because the patient can be null
private PatientEntity patient;

@OneToMany(mappedBy = "caseEntity", cascade = CascadeType.ALL, orphanRemoval = true)
@OrderBy("createdAt DESC")
private List<CaseNoteEntity> notes = new ArrayList<>();

public CaseEntity() {}

public CaseEntity(UUID id, String status, UUID ownerId, String title, String description, Instant createdAt, PatientEntity patient) {
public CaseEntity(UUID id, String status, UUID ownerId, String title, String description, Instant createdAt, PatientEntity patient, List<CaseNoteEntity> notes) {
this.id = id;
this.status = status;
this.ownerId = ownerId;
this.title = title;
this.description = description;
this.createdAt = createdAt;
this.patient = patient;
this.notes = notes != null ? notes : new ArrayList<>();
}

public UUID getId() { return id; }
Expand Down Expand Up @@ -61,4 +68,7 @@ public CaseEntity(UUID id, String status, UUID ownerId, String title, String des

public PatientEntity getPatient() { return patient; }
public void setPatient(PatientEntity patient) { this.patient = patient; }

public List<CaseNoteEntity> getNotes() { return notes; }

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.example.projektarendehantering.infrastructure.persistence;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.time.Instant;
import java.util.UUID;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "case_notes")
public class CaseNoteEntity {

@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "case_id")
private CaseEntity caseEntity;

private String content;

private String author;

private Instant createdAt;


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.example.projektarendehantering.infrastructure.persistence;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.UUID;

@Repository
public interface CaseNoteRepository extends JpaRepository<CaseNoteEntity, UUID> {
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package org.example.projektarendehantering.presentation.dto;

import jakarta.validation.constraints.NotNull;

import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class CaseDTO {
Expand All @@ -12,9 +12,8 @@ public class CaseDTO {
private String title;
private String description;
private Instant createdAt;

@NotNull
private UUID patientId;
private List<CaseNoteDTO> notes = new ArrayList<>();

public CaseDTO() {}

Expand Down Expand Up @@ -44,4 +43,7 @@ public CaseDTO(UUID id, String status, String title, String description, Instant

public UUID getPatientId() { return patientId; }
public void setPatientId(UUID patientId) { this.patientId = patientId; }

public List<CaseNoteDTO> getNotes() { return notes; }
public void setNotes(List<CaseNoteDTO> notes) { this.notes = notes; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.example.projektarendehantering.presentation.dto;

import java.time.Instant;
import java.util.UUID;

public class CaseNoteDTO {

private UUID id;
private String content;
private String author;
private Instant createdAt;

public CaseNoteDTO() {}

public CaseNoteDTO(UUID id, String content, String author, Instant createdAt) {
this.id = id;
this.content = content;
this.author = author;
this.createdAt = createdAt;
}

public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }

public String getContent() { return content; }
public void setContent(String content) { this.content = content; }

public String getAuthor() { return author; }
public void setAuthor(String author) { this.author = author; }

public Instant getCreatedAt() { return createdAt; }
public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import jakarta.validation.Valid;
import java.security.Principal;
import java.util.UUID;

@Controller
Expand All @@ -29,6 +31,13 @@ public UiController(CaseService caseService, PatientService patientService, Head
this.currentUserAdapter = currentUserAdapter;
}

@PostMapping("/ui/cases/{caseId}/notes")
public String addNote(@PathVariable UUID caseId, @RequestParam("content") String content, Principal principal) {
String author = principal != null ? principal.getName() : "Anonymous";
caseService.addNote(caseId, content, author);
return "redirect:/ui/cases/" + caseId;
}

@GetMapping("/")
public String index() {
return "index";
Expand Down
24 changes: 24 additions & 0 deletions src/main/resources/templates/cases/detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,30 @@ <h1>Case</h1>
<div class="v" th:text="${case.createdAt}">Date</div>
</div>
</section>

<section class="panel" th:if="${case != null}">
<h2>Notes</h2>
<div th:each="note : ${case.notes}" class="hint" style="margin-bottom: 10px;">
<p th:text="${note.content}">Note content</p>
<div class="muted" style="font-size: 0.8em;">
<span th:text="${note.author}">Author</span> -
<span th:text="${#instants.format(note.createdAt, 'yyyy-MM-dd HH:mm')}">Date</span>
</div>
</div>
<p th:if="${#lists.isEmpty(case.notes)}" class="muted">No notes yet.</p>

<hr style="border: 0; border-top: 1px solid var(--border); margin: 20px 0;"/>

<h3>Add Note</h3>
<form th:action="@{/ui/cases/{id}/notes(id=${case.id})}" method="post" class="form">
<label class="field">
<textarea class="input" name="content" rows="3" placeholder="Write a note..." required></textarea>
</label>
<div class="actions">
<button class="button" type="submit">Post Note</button>
</div>
</form>
</section>
<section class="panel panel-error" th:if="${case == null}">
<h2>Error</h2>
<p>Case not found.</p>
Expand Down