b87TViTOxGc{FmkLm*&wZ~s277#s1
zo#n{*j$J?7Q?j=ukDRo`A^sIvBVtz*dP<@7Z)8t-R^9ioe9E8hSYNHJ^xo6PkMiCM
zKb(mjj$*Bp-Ah@QWY(WaqSzImEASejM!p^Dp*BHW9;NF4Y93u{JK*=4Q^fNcrQ+
zQ}ym_!pOasMUV8Q3-DYq*RC%oCY{(dwgf4EwX`LKo@*7Z^Jc=n7rX!L)l5geoS7ZH
z)`t*#DFHn)^xH;AOb44&{~17Va%~=$Um8G=BqB8&hAn8c6zi3^{5mx_k
zr{-s$u%4IMOJK+CW}S6%y1At)o&98{MMM6%F~FDIt1EvRa`Vc|JgBi$Za?xt)|Bh_
z4cOuXj$XN2U)zR5F013m0uW;XvWAZVLM5&-;2V77OqE~8@G~VCnQa^
z%wj^XC-XsqhUL~V9Wue=BS-h72VPb>0FcdHmlx@&tp$Bl?7YMG?kTvR2z*lV?L-k<
zuKwjXE8@9M1{M0beXYVP6kEY{}f_%tkURz4;
zc&uhTWXZ11OHUtG%$m4s)9vHL49$O=IJvib;_WL{6RVD2&Hn5f<4H_YT;_~i7~mw<
zDDT3G0yU;F(N$%k+JlK{nJn7%`6{F{+tusE!K;|9M$(4XV9thc$|9o=<-n(ubL>AB
zb*9zAbVzFaW1mRT(Q=tL5)|ug1lV_xI{>HF8SOlW4n?d~TuA&r9MOcNpIidJYF4atUgl?b-MM)|O*ideS=<>l1DVd7
zTRlW+A+r7A^y+WNf>Ay`M$GFwcs#XAMKUYv^&Jaoi8FfD&;l#)C1cK)5*d&0G9v5zh?<|cmY;4O>yK`OkR0OR-
z5X6bjFPds^!74yDIc5GYc%^Ld#eEY)`+ow~u>Fro_O8OI9D$}dH%o>LRiZTJHb5Z2
zAFG^c@fHZYS}&<0NdanhP;VNH
z`hioCmn`uavcbK3q}U-{tf9QxyCARd0x;I{MXv;sQxV)dfL~>pix6TU5@QqX*3U
zY55&82QT7UcTgIImWap_IH1&y?vYMDR^IX6H>(@#+=nUt)0iq9EZystqupK9yqZ<|nKo*|kJJ>@HH
zYc|%0r}&)p!4tABbSjmn3R$ble4aB+x3Paacuot=qZ1gcDXoY(SXY9D%73rw-XWVs
zdD@`tE!Xc;SJc3s;ka4yjh~~f%wI~LYI0D90CQVNZ!;GeHs@f#@hv-6A?1(Qyul35
zIvs@%%0C26Hm?3H_X#RH{E*>k@K#?dCC?%nO`HqmY4eRUEuhzUFeX_0FD#_da^}#^
zs<$9wmLL-+qJ{SN2t+>sUZIC`X}c8~1O+$0E>15On||bnZ&zD<+81>5
zKrJboM_IE_<3pog2e(dq6~EFvUg2LJD1@utvrXDP=`i+|V{&1}loY=GMoIdzB&5#p
zkzu9*CSthzx&TDI8CIAf{m==1?mr){|KH!H|6Vtw7)KdJ*d5%sHPYnVnHpm^!hZoC
ClQzBp
literal 0
HcmV?d00001
diff --git a/src/static/js/custom.js b/src/static/js/custom.js
index f77b435..8b8b6fd 100644
--- a/src/static/js/custom.js
+++ b/src/static/js/custom.js
@@ -8,7 +8,9 @@ $(document).ready(() => {
activateTooltips();
pageLoadMotionEffects();
- $("select").select2({theme: "bootstrap-5", minimumResultsForSearch: -1})
+ // $("select").select2({theme: "bootstrap-5", minimumResultsForSearch: -1})
+
+ $("#headerTitle").text(document.title);
});
@@ -58,3 +60,8 @@ jQuery.expr[':'].icontains = function(a, i, m) {
const findByKey = (array, key, value) => {
return array.find(item => item[key] === value);
}
+
+function isEmpty(obj) {
+ return Object.keys(obj).length === 0;
+}
+
\ No newline at end of file
diff --git a/src/static/js/mainapp/anglers.js b/src/static/js/mainapp/anglers.js
index 10ad73b..be3c450 100644
--- a/src/static/js/mainapp/anglers.js
+++ b/src/static/js/mainapp/anglers.js
@@ -27,6 +27,16 @@ $(document).ready(() => {
fetchAndLoadGroups();
});
+ const showGroupsValue = localStorage.getItem("showGroups");
+ if (showGroupsValue !== null) {
+ $("#sortForm input[name='showGroups']").val([showGroupsValue]);
+ }
+
+ const sortAnglersValue = localStorage.getItem("sortAnglers");
+ if (sortAnglersValue !== null) {
+ $("#sortForm input[name='sortAnglers']").val([sortAnglersValue]);
+ }
+
// Modals
$("#addAngler").on("click", () => {
@@ -51,7 +61,7 @@ function fetchAndLoadGroups() {
const showGroups = localStorage.getItem("showGroups");
const sortAnglers = localStorage.getItem("sortAnglers");
const task = showGroups === "teams" ? "get-teams" : "get-sections";
-
+ const search = $("#search").val()
$.ajax({
type: "POST",
url: pageUrl,
@@ -59,7 +69,7 @@ function fetchAndLoadGroups() {
csrfmiddlewaretoken: csrfMiddlewareToken,
tasks: [task, "get-anglers"],
sortAnglers: sortAnglers,
- search: $("#search").val()
+ search: isEmptyOrSpaces(search) ? "" : search,
},
error: (error) => {
console.error(error);
@@ -74,18 +84,20 @@ function fetchAndLoadGroups() {
function groupTemplate(group, groupType, oppositeGroupType) {
groupValue = groupType === "teams" ? group.number : group.character
+ const nonPluralGroupType = groupType.slice(0, -1);
+ const editFunction = groupType === "teams"? "addTeam" : "addSection";
return `
+ class='${nonPluralGroupType.toLowerCase()} px-4 py-3 bg-body-tertiary bg-gradient rounded h-100 fluid-hover-zoom shadow-sm md-shadow-on-hover'
+ data-id='${group.id}' data-value='${groupValue}'>
- ${groupType.toUpperCase()}
+ ${nonPluralGroupType.toUpperCase()}
${groupValue}
-
+
@@ -104,7 +116,7 @@ function anglerTemplate(angler, oppositeGroupType) {
oppositeGroup = oppositeGroup.charAt(0).toUpperCase() + oppositeGroup.slice(1);
return `
-
+
-
+
@@ -140,10 +152,15 @@ function loadGroups(data) {
$("#groups").html("");
+ if (!groups.length) {
+ $("#notFound").show();
+ return;
+ }
+
groups.forEach((group) => {
$("#groups").append(groupTemplate(group, groupType, oppositeGroupType));
data.anglers.forEach((angler) => {
- if (angler.team_id === group.id || angler.section_id === group.id) {
+ if ((groupType == "teams" && angler.team_id === group.id) || (groupType == "sections" && angler.section_id === group.id)) {
$("#groups").find(".anglers").last().append(
anglerTemplate(angler, oppositeGroupType)
);
@@ -152,6 +169,13 @@ function loadGroups(data) {
});
activateTooltips();
+
+ if (!isEmptyOrSpaces($("#search").val())) {
+ $("#groups").find('.angler-fullname').each(function() {
+ var regex = new RegExp($("#search").val(), 'gi');
+ $(this).html($(this).text().replace(regex, '
$& '));
+ });
+ }
}
/**
@@ -177,7 +201,182 @@ function toggleLoading(loading) {
* @param {Number} anglerId - ID of the angler, if -1 will create a new angler
*/
function addAngler(anglerId) {
+
+ // Reset the form values
+ $("#anglerTitle").text("Add New Angler");
+ $("#anglerForename").val("");
+ $("#anglerSurname").val("");
+ $("#anglerTeam").empty().trigger("change");
+ $("#anglerSection").empty().trigger("change");
+ $("#anglerPeg").val(1);
+ $("#anglerForm .error").text("").hide();
+ $("#anglerDelete").hide();
+
+ function validateSection() {
+ const sectionId = $("#anglerSection").val();
+
+ var valid = true;
+
+ // Ensure that no teammates are in this section
+ const teamId = $("#anglerTeam").val();
+ $(`.team[data-id='${teamId}'] .angler`).each(function() {
+ if ($(this).data("section-id") == sectionId && $(this).data("id") != anglerId) {
+ valid = false;
+ return false;
+ }
+ else {
+ $("#anglerSectionError").text("").hide();
+ }
+ });
+
+ return valid;
+ }
+
+ $("#anglerSection").change(() => {validateSection()});
+
+ $.ajax({
+ type: "POST",
+ url: pageUrl,
+ data: {
+ csrfmiddlewaretoken: csrfMiddlewareToken,
+ tasks: ["get-teams", "get-sections"]
+ },
+ error: (error) => {
+ console.error(error);
+ },
+ success: (data) => {
+ data.teams.forEach((team) => {
+ $("#anglerTeam").append(`
Team ${team.number} `);
+ });
+ data.sections.forEach((section) => {
+ $("#anglerSection").append(`
Section ${section.character} `);
+ });
+
+ if (anglerId !== -1) {
+ const angler = $(`.angler[data-id='${anglerId}']`)
+ const forename = angler.data("first");
+ const surname = angler.data("last");
+ const peg = angler.data("peg-number");
+ const teamId = angler.data("team-id");
+ const sectionId = angler.data("section-id");
+
+ $("#anglerTitle").text(`Edit ${forename} ${surname}`);
+ $("#anglerForename").val(forename);
+ $("#anglerSurname").val(surname);
+ $("#anglerTeam").val(teamId).trigger("change");
+ $("#anglerSection").val(sectionId).trigger("change");
+ $("#anglerPeg").val(peg);
+ $("#anglerDelete").show();
+ }
+ }
+ });
+
$("#anglerModal").modal("show");
+
+ $("#anglerForm").off("submit").on("submit", (e) => {
+ e.preventDefault();
+
+ $("#anglerForm .error").text("").hide();
+
+ const forename = $("#anglerForename").val();
+ const surname = $("#anglerSurname").val();
+ const teamId = $("#anglerTeam").val();
+ const sectionId = $("#anglerSection").val();
+ const peg = $("#anglerPeg").val();
+ const validSection = validateSection();
+1
+ var formErrors = !(forename && surname && teamId && sectionId && peg && validSection);
+
+ // This form validation is not very scalable
+ if (!forename) {
+ $("#anglerForenameError").text("Please enter a forename").show();
+ }
+ if (!surname) {
+ $("#anglerSurnameError").text("Please enter a surname").show();
+ }
+ if (!teamId) {
+ $("#anglerTeamError").text("Please select a team").show();
+ }
+ if (!sectionId) {
+ $("#anglerSectionError").text("Please select a section").show();
+ }
+ if (!peg) {
+ $("#anglerPegError").text("Please enter a peg number").show();
+ }
+ if (!validSection) {
+ $("#anglerSectionError").text("Anglers cannot share a section with a teammate").show();
+ }
+ if (formErrors) {
+ return;
+ }
+
+ $.ajax({
+ type: "POST",
+ url: pageUrl,
+ data: {
+ csrfmiddlewaretoken: csrfMiddlewareToken,
+ tasks: ["update-angler"],
+ angler_id: anglerId,
+ forename: forename,
+ surname: surname,
+ team_id: teamId,
+ section_id: sectionId,
+ peg_number: peg
+ },
+ error: (error) => {
+ console.error(error);
+ },
+ success: (data) => {
+ if (isEmpty(data.form_errors)) {
+ fetchAndLoadGroups();
+ $("#anglerModal").modal("hide");
+ return;
+ }
+
+ for(var inputId in data.form_errors) {
+ var errorMessage = data.form_errors[inputId];
+ $(`${inputId}Error`).text(errorMessage).show();
+ }
+ }
+ });
+ });
+
+ $("#anglerDelete").off("click").on("click", () => {
+ $.ajax({
+ type: "POST",
+ url: pageUrl,
+ data: {
+ csrfmiddlewaretoken: csrfMiddlewareToken,
+ tasks: ["delete-angler"],
+ angler_id: anglerId
+ },
+ error: (error) => {
+ console.error(error);
+ },
+ success: (data) => {
+ fetchAndLoadGroups();
+ $("#anglerModal").modal("hide");
+ alert("Angler Deleted");
+ }
+ });
+ });
+
+ $("#anglerPegNext").off("click").on("click", () => {
+ $.ajax({
+ type: "POST",
+ url: pageUrl,
+ data: {
+ csrfmiddlewaretoken: csrfMiddlewareToken,
+ tasks: ["get-nextPegNumber"]
+ },
+ error: (error) => {
+ console.error(error);
+ },
+ success: (data) => {
+ $("#anglerPeg").val(data.nextPegNumber);
+ }
+ });
+ });
}
/**
@@ -186,7 +385,96 @@ function addAngler(anglerId) {
* @param {Number} teamId - ID of the team, if -1 will create a new team
*/
function addTeam(teamId) {
+
+ // Reset the form values
+ $("#teamNumberError").text("").hide();
+
+ if (teamId !== -1) {
+ const team = $(`.team[data-id='${teamId}']`)
+ const number = team.data("value");
+
+ $("#teamTitle").text(`Edit Team #${number}`);
+ $("#teamNumber").val(number);
+ $("#teamDelete").show();
+ }
+ else {
+ $("#teamTitle").text("Add New Team");
+ $("#teamNumber").val(1);
+ $("#teamDelete").hide();
+ }
+
$("#teamModal").modal("show");
+
+ $("#teamForm").off("submit").on("submit", (e) => {
+ e.preventDefault();
+
+ const number = $("#teamNumber").val();
+ if (!number) {
+ $("#teamNumberError").text("Please enter a team number").show();
+ return;
+ }
+
+ $.ajax({
+ type: "POST",
+ url: pageUrl,
+ data: {
+ csrfmiddlewaretoken: csrfMiddlewareToken,
+ tasks: ["update-team"],
+ id: teamId,
+ number: number
+ },
+ error: (error) => {
+ console.error(error);
+ },
+ success: (data) => {
+ if (isEmpty(data.form_errors)) {
+ fetchAndLoadGroups();
+ $("#teamModal").modal("hide");
+ return;
+ }
+ for(var inputId in data.form_errors) {
+ var errorMessage = data.form_errors[inputId];
+ $(`${inputId}Error`).text(errorMessage).show();
+ }
+ }
+ });
+ });
+
+ $("#teamDelete").off("click").on("click", () => {
+ $.ajax({
+ type: "POST",
+ url: pageUrl,
+ data: {
+ csrfmiddlewaretoken: csrfMiddlewareToken,
+ tasks: ["delete-team"],
+ team_id: teamId
+ },
+ error: (error) => {
+ console.error(error);
+ },
+ success: (data) => {
+ fetchAndLoadGroups();
+ $("#teamModal").modal("hide");
+ }
+ });
+ });
+
+ $("#teamNumberNext").off("click").on("click", () => {
+ $.ajax({
+ type: "POST",
+ url: pageUrl,
+ data: {
+ csrfmiddlewaretoken: csrfMiddlewareToken,
+ tasks: ["get-nextTeamNumber"]
+ },
+ error: (error) => {
+ console.error(error);
+ },
+ success: (data) => {
+ $("#teamNumber").val(data.nextTeamNumber);
+ }
+ });
+ });
}
/**
diff --git a/src/templates/base.html b/src/templates/base.html
index 94a1532..1cb3765 100644
--- a/src/templates/base.html
+++ b/src/templates/base.html
@@ -3,7 +3,7 @@
-
{% block title %}{% endblock title %}AT Results
+
{% block title %}{% endblock title %}Angling Trust Results
{% load static %}
@@ -14,9 +14,60 @@
{% block style %}
{% endblock style %}
-
- {% block content %}
- {% endblock content %}
+
+
+
+
+
+
+
+
+ {% block header_buttons %}
+ {% endblock header_buttons %}
+
+
+
+ {% block content %}
+ {% endblock content %}
+
+
+
+
+