diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index e0c4f3f7804..68c58fdeb6d 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -47,16 +47,6 @@
to_chat(usr, "ERROR: Mob not found.", confidential = TRUE)
return
cmd_show_exp_panel(M.client)
-
- else if(href_list["toggleexempt"])
- if(!check_rights(R_ADMIN))
- return
- var/client/C = locate(href_list["toggleexempt"]) in GLOB.clients
- if(!C)
- to_chat(usr, "ERROR: Client not found.", confidential = TRUE)
- return
- toggle_exempt_status(C)
-
else if(href_list["makeAntag"])
if(!check_rights(R_ADMIN))
return
diff --git a/code/modules/jobs/job_report.dm b/code/modules/jobs/job_report.dm
index 88c7f7ad190..102d4d5f666 100644
--- a/code/modules/jobs/job_report.dm
+++ b/code/modules/jobs/job_report.dm
@@ -17,6 +17,13 @@
ui = new(user, src, "TrackedPlaytime")
ui.open()
+/datum/job_report_menu/ui_data(mob/user)
+ var/list/data = list()
+
+ data["exemptStatus"] = (owner.prefs?.db_flags & DB_FLAG_EXEMPT)
+
+ return data
+
/datum/job_report_menu/ui_static_data()
if (!CONFIG_GET(flag/use_exp_tracking))
return list("failReason" = JOB_REPORT_MENU_FAIL_REASON_TRACKING_DISABLED)
@@ -43,7 +50,39 @@
data["livingTime"] = play_records[EXP_TYPE_LIVING]
data["ghostTime"] = play_records[EXP_TYPE_GHOST]
+ data["isAdmin"] = check_rights(R_ADMIN)
+
return data
+/datum/job_report_menu/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
+ . = ..()
+ if(.)
+ return
+
+ switch(action)
+ if("toggle_exempt")
+ if(!check_rights(R_ADMIN))
+ message_admins("[ADMIN_LOOKUPFLW(usr)] attempted to toggle job playtime exempt status without admin rights.")
+ log_admin("[ADMIN_LOOKUPFLW(usr)] attempted to toggle job playtime exempt status without admin rights.")
+ to_chat(usr, "ERROR: Insufficient admin rights.", confidential = TRUE)
+ return TRUE
+
+ var/datum/admins/viewer_admin_datum = GLOB.admin_datums[usr.ckey]
+
+ if(!viewer_admin_datum)
+ message_admins("[ADMIN_LOOKUPFLW(usr)] attempted to toggle job playtime exempt status without admin datum for their ckey.")
+ log_admin("[ADMIN_LOOKUPFLW(usr)] attempted to toggle job playtime exempt status without admin datum for their ckey.")
+ to_chat(usr, "ERROR: Insufficient admin rights.", confidential = TRUE)
+ return TRUE
+
+ var/client/owner_client = locate(owner) in GLOB.clients
+
+ if(!owner_client)
+ to_chat(usr, "ERROR: Client not found.", confidential = TRUE)
+ return TRUE
+
+ viewer_admin_datum.toggle_exempt_status(owner_client)
+ return TRUE
+
#undef JOB_REPORT_MENU_FAIL_REASON_TRACKING_DISABLED
#undef JOB_REPORT_MENU_FAIL_REASON_NO_RECORDS
diff --git a/tgui/packages/tgui/interfaces/TrackedPlaytime.js b/tgui/packages/tgui/interfaces/TrackedPlaytime.js
index d6ee9c01775..e3caae59062 100644
--- a/tgui/packages/tgui/interfaces/TrackedPlaytime.js
+++ b/tgui/packages/tgui/interfaces/TrackedPlaytime.js
@@ -1,6 +1,6 @@
import { sortBy } from "common/collections";
import { useBackend } from "../backend";
-import { Box, Flex, ProgressBar, Section, Table } from "../components";
+import { Box, Button, Flex, ProgressBar, Section, Table } from "../components";
import { Window } from "../layouts";
const JOB_REPORT_MENU_FAIL_REASON_TRACKING_DISABLED = 1;
@@ -46,11 +46,13 @@ const PlaytimeSection = props => {
};
export const TrackedPlaytime = (props, context) => {
- const { data } = useBackend(context);
+ const { act, data } = useBackend(context);
const {
failReason,
jobPlaytimes,
specialPlaytimes,
+ exemptStatus,
+ isAdmin,
livingTime,
ghostTime,
} = data;
@@ -75,8 +77,18 @@ export const TrackedPlaytime = (props, context) => {
}}
/>
-
-
+ act("toggle_exempt")}>
+ Job Playtime Exempt
+
+ )}>
+