diff --git a/CHANGELOG.md b/CHANGELOG.md
index 435e3ebea4bc9b2a9b398105fcdbe866878791b6..cbede3e093d3a5ce45172220992cc6ad6403784c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,11 +9,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ### Added
 
+### Changed
+
+### Fixed
+
+## [2.1.5]
+
 ### Changed
 - Job offer import now includes job information. @rwbackx
+- Job offer information can now always be viewed. @rwbackx
 
 ### Fixed
 - TA training template file was not working. @rwbackx
+- Searching for job offers would error if there were no results. @rwbackx
+- Hiring and rejection messages could not be edited. @rwbackx
 
 ## [2.1.4]
 
diff --git a/build.gradle.kts b/build.gradle.kts
index 4e4e442f56e6502f76a30cb981a4572a58371d13..0e9a64c1a795084bc21187cbb3a86ffcab354a98 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -4,7 +4,7 @@ import nl.javadude.gradle.plugins.license.DownloadLicensesExtension
 import nl.javadude.gradle.plugins.license.LicenseExtension
 
 group = "nl.tudelft.tam"
-version = "2.1.4"
+version = "2.1.5"
 
 val javaVersion = JavaVersion.VERSION_17
 
diff --git a/src/main/java/nl/tudelft/tam/service/CourseService.java b/src/main/java/nl/tudelft/tam/service/CourseService.java
index 68413987b608ad70f94d0183be2a2cd59ad7d46d..10673c00c514dec0f4b3315b9672fe73d7e5f759 100644
--- a/src/main/java/nl/tudelft/tam/service/CourseService.java
+++ b/src/main/java/nl/tudelft/tam/service/CourseService.java
@@ -17,6 +17,7 @@
  */
 package nl.tudelft.tam.service;
 
+import java.util.Collections;
 import java.util.List;
 
 import javax.validation.constraints.NotNull;
@@ -67,6 +68,8 @@ public class CourseService {
 	 * @return     The list of course details
 	 */
 	public List<CourseDetailsDTO> getCoursesById(List<Long> ids) {
+		if (ids.isEmpty())
+			return Collections.emptyList();
 		return courseApi.getAllCoursesById(ids).collectList().block();
 	}
 
diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties
index 3e00a8743fc806022e91bc58cfb451fd9d055fe9..4d5e017dc2ed8c163a57a669f063f81ff5533c34 100644
--- a/src/main/resources/messages.properties
+++ b/src/main/resources/messages.properties
@@ -151,10 +151,10 @@ jobOffer.hiringMessage.blank = Currently no hiring message configured.
 jobOffer.hiringMessage.enter = An optional message that a student will see after receiving the offer...
 jobOffer.rejectMessage = Rejection Message
 jobOffer.rejectMessage.enter = An optional message that a rejected student will see...
-jobOffer.rejectMessage.view = View Rejection Message
+jobOffer.rejectMessage.view = View rejection message
 jobOffer.hiringMessage.edit = Edit Hiring Message
 jobOffer.hiringMessage.add = Add Hiring Message
-jobOffer.hiringMessage.view = View Hiring Message
+jobOffer.hiringMessage.view = View hiring message
 jobOffer.details = Job Offer Details
 jobOffer.edit = Edit Job Offer
 jobOffer.closeDeadline = Close New Applications
@@ -186,6 +186,7 @@ jobOffer.requireResponse = Require response to job information
 jobOffer.responseRequired = This job offer requires a response to the above information.
 jobOffer.providesInformation = This job offer provides the following information:
 jobOffer.providesNoInformation = This job offer provides no additional information.
+jobOffer.noResults.description = No job offers matching your search found.
 
 application.all = All Applications
 application.my = My Applications
diff --git a/src/main/resources/templates/job_offer/apply.html b/src/main/resources/templates/job_offer/apply.html
index 20e119f14a57f2f47dfd34aa2a01f20d9ae8bb0e..32cae5f01876cbc25303b4b172acfb5b87da0f75 100644
--- a/src/main/resources/templates/job_offer/apply.html
+++ b/src/main/resources/templates/job_offer/apply.html
@@ -26,6 +26,7 @@
         <dialog
             th:fragment="overlay"
             th:id="|apply-${offer.id}-overlay|"
+            th:attr="data-closable=${app.exists() ? 'true' : null}"
             class="dialog"
             th:styleappend="${offer.requireApplicationText} ? '--width: 40rem;' : ''">
             <form class="flex vertical p-7" th:action="@{/application/submit}" th:method="post">
@@ -70,10 +71,11 @@
                     <button
                         type="button"
                         class="button p-less"
-                        data-style="outlined"
+                        th:data-style="${app.exists()} ? 'filled' : 'outlined'"
                         th:text="#{general.close}"
                         data-cancel></button>
                     <button
+                        th:unless="${app.exists()}"
                         type="submit"
                         class="button p-less"
                         th:text="#{jobOffer.apply}"></button>
diff --git a/src/main/resources/templates/job_offer/view_many.html b/src/main/resources/templates/job_offer/view_many.html
index ad7858103f30d2eb8fa4c8e85da7b09bdcabc024..deb890ff3fd6eee722fd1fd5ac3bcbcb87238732 100644
--- a/src/main/resources/templates/job_offer/view_many.html
+++ b/src/main/resources/templates/job_offer/view_many.html
@@ -130,82 +130,79 @@
                                     th:text="#{application.status.rejected}"></span>
                             </td>
                             <td th:text="${offer.name}"></td>
-                            <td th:unless="${app.exists()}">
+                            <td>
                                 <div class="flex gap-3 justify-end wrap | md:gap-2">
                                     <button
                                         class="button p-min"
                                         data-style="outlined"
                                         th:data-dialog="|apply-${offer.id}-overlay|"
                                         th:text="#{jobOffer.viewDetails}"></button>
-                                </div>
-                                <th:block
-                                    th:if="${!app.exists()}"
-                                    th:replace="~{job_offer/apply :: overlay}"></th:block>
-                            </td>
-                            <td th:if="${app.exists()}">
-                                <div class="flex gap-3 justify-end wrap | md:gap-2">
-                                    <button
-                                        th:if="${app.exists() && (status == 'ACCEPTED' || status == 'OFFERED') && !(offer.hiringMessage == null || offer.hiringMessage.isEmpty())}"
-                                        class="button p-min"
-                                        data-style="outlined"
-                                        th:data-dialog="|view-hiring-message-overlay-${offer.id}|"
-                                        th:text="#{jobOffer.hiringMessage.view}"></button>
-                                    <button
-                                        th:if="${app.exists() && status == 'REJECTED_BY_TEACHER' && !(offer.rejectMessage == null || offer.rejectMessage.isEmpty())}"
-                                        class="button p-min"
-                                        data-style="outlined"
-                                        th:data-dialog="|view-reject-message-overlay-${offer.id}|"
-                                        th:text="#{jobOffer.rejectMessage.view}"></button>
-                                    <form
-                                        th:if="${status == 'OFFERED'}"
-                                        th:action="@{|/application/accept/${offer.id}|}"
-                                        method="post"
-                                        data-scroll-to="true">
-                                        <input
-                                            th:if="${param.program}"
-                                            type="hidden"
-                                            name="program"
-                                            th:value="${param.program}" />
-                                        <input
-                                            th:if="${param.q}"
-                                            type="hidden"
-                                            name="q"
-                                            th:value="${param.q}" />
-                                        <input type="hidden" name="page" value="job-offers" />
-                                        <button
-                                            type="submit"
-                                            class="button p-min"
-                                            data-type="accept">
-                                            <span class="fa-solid fa-check"></span>
-                                            <span th:text="#{jobOffer.accept}"></span>
-                                        </button>
+                                    <th:block th:replace="~{job_offer/apply :: overlay}"></th:block>
+
+                                    <th:block th:if="${app.exists()}">
                                         <button
-                                            th:data-dialog="|confirm-retract-app-${offer.id}|"
-                                            type="button"
+                                            th:if="${app.exists() && (status == 'ACCEPTED' || status == 'OFFERED') && !(offer.hiringMessage == null || offer.hiringMessage.isEmpty())}"
                                             class="button p-min"
-                                            data-type="error">
-                                            <span class="fa-solid fa-xmark"></span>
-                                            <span
-                                                th:if="${status == 'OFFERED'}"
-                                                th:text="#{jobOffer.reject}"></span>
-                                            <span
-                                                th:unless="${status == 'OFFERED'}"
-                                                th:text="#{jobOffer.retract}"></span>
-                                        </button>
-                                    </form>
-                                    <div th:if="${status == 'SUBMITTED'}" data-scroll-to="true">
+                                            data-style="outlined"
+                                            th:data-dialog="|view-hiring-message-overlay-${offer.id}|"
+                                            th:text="#{jobOffer.hiringMessage.view}"></button>
                                         <button
-                                            th:data-dialog="|confirm-retract-app-${offer.id}|"
+                                            th:if="${app.exists() && status == 'REJECTED_BY_TEACHER' && !(offer.rejectMessage == null || offer.rejectMessage.isEmpty())}"
                                             class="button p-min"
                                             data-style="outlined"
-                                            data-type="error">
-                                            <span class="fa-solid fa-xmark"></span>
-                                            <span th:text="#{jobOffer.retract}"></span>
-                                        </button>
-                                    </div>
-                                    <th:block th:unless="${app.status.handled()}">
-                                        <th:block
-                                            th:replace="~{job_offer/confirm_retract_app :: overlay}"></th:block>
+                                            th:data-dialog="|view-reject-message-overlay-${offer.id}|"
+                                            th:text="#{jobOffer.rejectMessage.view}"></button>
+                                        <form
+                                            th:if="${status == 'OFFERED'}"
+                                            th:action="@{|/application/accept/${offer.id}|}"
+                                            method="post"
+                                            data-scroll-to="true">
+                                            <input
+                                                th:if="${param.program}"
+                                                type="hidden"
+                                                name="program"
+                                                th:value="${param.program}" />
+                                            <input
+                                                th:if="${param.q}"
+                                                type="hidden"
+                                                name="q"
+                                                th:value="${param.q}" />
+                                            <input type="hidden" name="page" value="job-offers" />
+                                            <button
+                                                type="submit"
+                                                class="button p-min"
+                                                data-type="accept">
+                                                <span class="fa-solid fa-check"></span>
+                                                <span th:text="#{jobOffer.accept}"></span>
+                                            </button>
+                                            <button
+                                                th:data-dialog="|confirm-retract-app-${offer.id}|"
+                                                type="button"
+                                                class="button p-min"
+                                                data-type="error">
+                                                <span class="fa-solid fa-xmark"></span>
+                                                <span
+                                                    th:if="${status == 'OFFERED'}"
+                                                    th:text="#{jobOffer.reject}"></span>
+                                                <span
+                                                    th:unless="${status == 'OFFERED'}"
+                                                    th:text="#{jobOffer.retract}"></span>
+                                            </button>
+                                        </form>
+                                        <div th:if="${status == 'SUBMITTED'}" data-scroll-to="true">
+                                            <button
+                                                th:data-dialog="|confirm-retract-app-${offer.id}|"
+                                                class="button p-min"
+                                                data-style="outlined"
+                                                data-type="error">
+                                                <span class="fa-solid fa-xmark"></span>
+                                                <span th:text="#{jobOffer.retract}"></span>
+                                            </button>
+                                        </div>
+                                        <th:block th:unless="${app.status.handled()}">
+                                            <th:block
+                                                th:replace="~{job_offer/confirm_retract_app :: overlay}"></th:block>
+                                        </th:block>
                                     </th:block>
                                 </div>
                             </td>
@@ -223,13 +220,17 @@
 
             <div th:if="${editions.isEmpty()}">
                 <span
-                    th:if="${param.program}"
+                    th:if="${param.program} and not ${param.q}"
                     class="empty_description"
                     th:text="#{jobOffer.empty.description}"></span>
                 <span
-                    th:unless="${param.program}"
+                    th:if="not ${param.program} and not ${param.q}"
                     class="empty_description"
                     th:text="#{jobOffer.selectProgram}"></span>
+                <span
+                    th:if="${param.q}"
+                    class="empty_description"
+                    th:text="#{jobOffer.noResults.description}"></span>
             </div>
 
             <script th:inline="text">
diff --git a/src/main/resources/templates/job_offer/view_one.html b/src/main/resources/templates/job_offer/view_one.html
index be04f8f37c8f4d7722b6a777a5031af9c296e749..d6e0fd484fdc988651ba195121c438c3b2d752b7 100644
--- a/src/main/resources/templates/job_offer/view_one.html
+++ b/src/main/resources/templates/job_offer/view_one.html
@@ -227,6 +227,7 @@
                         <textarea
                             class="textfield"
                             data-style="variant"
+                            name="hiringMessage"
                             placeholder="Enter hiring message"
                             th:text="${offer.hiringMessage}"
                             rows="4"></textarea>
@@ -247,6 +248,7 @@
                         <textarea
                             class="textfield"
                             data-style="variant"
+                            name="rejectMessage"
                             placeholder="Enter rejection message"
                             th:text="${offer.rejectMessage}"
                             rows="4"></textarea>