From 2c211a93bc472db5609556a64bf6ce4cf3eb584d Mon Sep 17 00:00:00 2001
From: Robert Goldmann <deadlocker@gmx.de>
Date: Sun, 16 Oct 2022 11:54:01 +0200
Subject: [PATCH] #721 - added datepickers to select date range

---
 .../budgetmaster/search/Search.java           |  6 +-
 .../src/main/resources/static/js/charts.js    |  2 +-
 .../src/main/resources/static/js/search.js    | 95 ++++++++++++++++++-
 .../resources/templates/search/search.ftl     |  6 ++
 .../templates/search/searchMacros.ftl         | 50 +++++++++-
 5 files changed, 152 insertions(+), 7 deletions(-)

diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/search/Search.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/search/Search.java
index 1587f38a3..f1e01a130 100644
--- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/search/Search.java
+++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/search/Search.java
@@ -1,5 +1,7 @@
 package de.deadlocker8.budgetmaster.search;
 
+import org.springframework.format.annotation.DateTimeFormat;
+
 import java.time.LocalDate;
 
 public class Search
@@ -13,7 +15,9 @@ public class Search
 	private boolean searchTags;
 	private boolean includeHiddenAccounts;
 	private int page;
+	@DateTimeFormat(pattern = "dd.MM.yyyy")
 	private LocalDate startDate;
+	@DateTimeFormat(pattern = "dd.MM.yyyy")
 	private LocalDate endDate;
 
 	public Search()
@@ -127,7 +131,7 @@ public class Search
 
 	public boolean isEmptySearch()
 	{
-		return !searchName && !searchDescription && !searchCategory && !searchTags && startDate == null && endDate == null;
+		return !searchName && !searchDescription && !searchCategory && !searchTags;
 	}
 
 	@Override
diff --git a/BudgetMasterServer/src/main/resources/static/js/charts.js b/BudgetMasterServer/src/main/resources/static/js/charts.js
index 4a441e796..6296f249e 100644
--- a/BudgetMasterServer/src/main/resources/static/js/charts.js
+++ b/BudgetMasterServer/src/main/resources/static/js/charts.js
@@ -21,7 +21,7 @@ $(document).ready(function()
     if($(".datepicker").length)
     {
         chartPickerStartDate = M.Datepicker.init(document.getElementById('chart-datepicker'), {
-            yearRange: 25,
+            yearRange: 50,
             firstDay: 1,
             showClearBtn: false,
             setDefaultDate: true,
diff --git a/BudgetMasterServer/src/main/resources/static/js/search.js b/BudgetMasterServer/src/main/resources/static/js/search.js
index 9207fab59..5f0d6f57b 100644
--- a/BudgetMasterServer/src/main/resources/static/js/search.js
+++ b/BudgetMasterServer/src/main/resources/static/js/search.js
@@ -1,3 +1,6 @@
+let searchPickerStartDate;
+let searchPickerEndDate;
+
 $(document).ready(function()
 {
     $('.page-link').click(function()
@@ -10,4 +13,94 @@ $(document).ready(function()
             document.getElementById('searchForm').submit();
         }
     });
-});
\ No newline at end of file
+
+    if($(".datepicker").length)
+    {
+        searchPickerStartDate = M.Datepicker.init(document.getElementById('search-datepicker'), {
+            yearRange: 50,
+            firstDay: 1,
+            showClearBtn: false,
+            setDefaultDate: startDate !== null,
+            defaultDate: startDate,
+            autoClose: true,
+
+            i18n: {
+                // Strings and translations
+                months: monthNames,
+                monthsShort: monthNamesShort,
+                weekdays: weekDays,
+                weekdaysShort: weekDaysShort,
+                weekdaysAbbrev: weekDaysLetters,
+
+                // Buttons
+                cancel: buttonCancel,
+                done: buttonClose,
+
+                // Accessibility labels
+                labelMonthNext: '>',
+                labelMonthPrev: '<'
+            },
+
+            // Formats
+            format: 'dd.mm.yyyy',
+            formatSubmit: 'dd.mm.yyyy',
+
+            onSelect: function()
+            {
+                if(typeof searchPickerEndDate !== "undefined")
+                {
+                    let selectedDate = searchPickerEndDate.date;
+                    searchPickerEndDate.destroy();
+                    searchPickerEndDate = createSearchDatePickerEnd(this.date, selectedDate);
+                }
+            }
+        });
+
+        // picker end date
+        if(typeof endDate !== "undefined")
+        {
+            searchPickerEndDate = createSearchDatePickerEnd(searchPickerStartDate.date, endDate);
+        }
+    }
+});
+
+function createSearchDatePickerEnd(minDate, selectedDate)
+{
+    if(selectedDate < minDate)
+    {
+        selectedDate = minDate;
+    }
+
+
+
+    return M.Datepicker.init(document.getElementById('search-datepicker-end'), {
+        yearRange: 50,
+        firstDay: 1,
+        showClearBtn: false,
+        setDefaultDate: true,
+        minDate: minDate,
+        defaultDate: selectedDate,
+        autoClose: true,
+
+        i18n: {
+            // Strings and translations
+            months: monthNames,
+            monthsShort: monthNamesShort,
+            weekdays: weekDays,
+            weekdaysShort: weekDaysShort,
+            weekdaysAbbrev: weekDaysLetters,
+
+            // Buttons
+            cancel: buttonCancel,
+            done: buttonClose,
+
+            // Accessibility labels
+            labelMonthNext: '>',
+            labelMonthPrev: '<'
+        },
+
+        // Formats
+        format: 'dd.mm.yyyy',
+        formatSubmit: 'dd.mm.yyyy'
+    });
+}
\ No newline at end of file
diff --git a/BudgetMasterServer/src/main/resources/templates/search/search.ftl b/BudgetMasterServer/src/main/resources/templates/search/search.ftl
index 2150f4d56..54c27d783 100644
--- a/BudgetMasterServer/src/main/resources/templates/search/search.ftl
+++ b/BudgetMasterServer/src/main/resources/templates/search/search.ftl
@@ -3,6 +3,7 @@
         <#import "../helpers/header.ftl" as header>
         <@header.globals/>
         <@header.header "BudgetMaster - ${locale.getString('search')}"/>
+        <@header.style "datepicker"/>
         <@header.style "transactions"/>
         <@header.style "search"/>
         <#import "/spring.ftl" as s>
@@ -26,6 +27,7 @@
                     <form id="searchForm" action="<@s.url '/search'/>" method="get">
                         <@searchMacros.searchTextAndButton search/>
                         <@searchMacros.checkboxes search/>
+                        <@searchMacros.dateRange search/>
                         <input type="hidden" name="page" id="inputPageNumber" value="${page.getNumber()}"/>
                     </form>
 
@@ -83,6 +85,10 @@
             </div>
         </main>
 
+        <!-- Pass localization to JS -->
+        <#import "../helpers/globalDatePicker.ftl" as datePicker>
+        <@datePicker.datePickerLocalization/>
+
         <!--  Scripts-->
         <#import "../helpers/scripts.ftl" as scripts>
         <@scripts.scripts/>
diff --git a/BudgetMasterServer/src/main/resources/templates/search/searchMacros.ftl b/BudgetMasterServer/src/main/resources/templates/search/searchMacros.ftl
index 3c011ca27..caf7c3f57 100644
--- a/BudgetMasterServer/src/main/resources/templates/search/searchMacros.ftl
+++ b/BudgetMasterServer/src/main/resources/templates/search/searchMacros.ftl
@@ -3,19 +3,19 @@
 
 <#macro searchTextAndButton search>
     <div class="row no-margin-bottom valign-wrapper">
-        <div class="col s10 m7 offset-m1 l6 offset-l2">
+        <div class="col s10 m6 offset-m2 l5 offset-l3">
             <div class="input-field">
                 <input id="searchText" type="text" name="searchText" value="${search.getSearchText()}">
                 <label for="searchText">${locale.getString("search")}</label>
             </div>
         </div>
 
-        <div class="col s2 m3 l4">
+        <div class="col s2 m4 l4">
             <div class="hide-on-small-only">
-                <@header.buttonSubmit name='action' icon='search' localizationKey='search.submit' id='button-save-account'/>
+                <@header.buttonSubmit name='action' icon='search' localizationKey='search.submit' id='button-perform-search'/>
             </div>
             <div class="hide-on-med-and-up">
-                <@header.buttonSubmit name='action' icon='search' localizationKey='' id='button-save-account'/>
+                <@header.buttonSubmit name='action' icon='search' localizationKey='' id='button-perform-search'/>
             </div>
         </div>
     </div>
@@ -66,6 +66,48 @@
     </div>
 </#macro>
 
+<#macro dateRange search>
+    <div class="row">
+        <div class="input-field col s6 m4 offset-m2 l3 offset-l3">
+            <#if search.getStartDate()??>
+                <#assign startDate = dateService.getLongDateString(search.getStartDate())/>
+                 <script>
+                    startDate = "${startDate}".split(".");
+                    startDate = new Date(startDate[2], startDate[1] - 1, startDate[0]);
+                 </script>
+            <#else>
+                <#assign startDate = ''/>
+                <script>
+                    startDate = null;
+                </script>
+            </#if>
+
+            <i class="material-icons prefix">today</i>
+            <input id="search-datepicker" type="text" class="datepicker" name="startDate" value="${startDate}">
+            <label for="search-datepicker">${locale.getString("chart.steps.second.label.start")}</label>
+        </div>
+
+        <div class="input-field col s6 m4 l3">
+            <#if search.getEndDate()??>
+                <#assign endDate = dateService.getLongDateString(search.getEndDate())/>
+                <script>
+                    endDate = "${endDate}".split(".");
+                    endDate = new Date(endDate[2], endDate[1] - 1, endDate[0]);
+                </script>
+            <#else>
+                <#assign endDate = ''/>
+                <script>
+                    endDate = null;
+                </script>
+            </#if>
+
+            <i class="material-icons prefix">event</i>
+            <input id="search-datepicker-end" type="text" class="datepicker" name="endDate" value="${endDate}">
+            <label for="search-datepicker-end">${locale.getString("chart.steps.second.label.end")}</label>
+        </div>
+    </div>
+</#macro>
+
 <#macro pagination page position>
     <div class="row pagination-position-${position}">
         <div class="col s12 center-align">
-- 
GitLab