From 22608f1aa742dee9c5f704e4ff4eed621d7d3ba7 Mon Sep 17 00:00:00 2001
From: Erik Thuning <boooink@gmail.com>
Date: Thu, 29 Feb 2024 14:48:37 +0100
Subject: [PATCH] Added a page intended for users to view their own loans. Also
 added serial numbers to loan listings for users.

---
 html/en/fragments.html   | 113 +++++++++++++++++++++++++++++++++++++--
 html/sv/fragments.html   | 113 +++++++++++++++++++++++++++++++++++++--
 include/Page.php         |  10 ++--
 include/ProductPage.php  |   9 ++--
 include/PublicPage.php   |  77 ++++++++++++++++++++++++++
 include/functions.php    |   2 +
 include/translations.php |  32 +++++++++++
 style.css                |   4 ++
 8 files changed, 342 insertions(+), 18 deletions(-)
 create mode 100644 include/PublicPage.php

diff --git a/html/en/fragments.html b/html/en/fragments.html
index daa9a89..11ffc9a 100644
--- a/html/en/fragments.html
+++ b/html/en/fragments.html
@@ -626,14 +626,17 @@
   ¤inactive_loans¤
 </div>
 
-¤¤ loan_table ¤¤
+¤¤ user_loan_table ¤¤
 <table class="history">
   <thead>
     <tr>
       <th class="status">
       </th>
       <th>
-        ¤item¤
+        Product
+      </th>
+      <th>
+        Serial number
       </th>
       <th>
         Start date
@@ -651,12 +654,15 @@
   </tbody>
 </table>
 
-¤¤ loan_table_row ¤¤
+¤¤ user_loan_table_row ¤¤
 <tr>
   <td class="status ¤status¤">
   </td>
   <td>
-    ¤item_link¤
+    ¤name¤
+  </td>
+  <td>
+    ¤serial¤
   </td>
   <td>
     ¤start_date¤
@@ -669,6 +675,105 @@
   </td>
 </tr>
 
+¤¤ product_loan_table ¤¤
+<table class="history">
+  <thead>
+    <tr>
+      <th class="status">
+      </th>
+      <th>
+        Borrower
+      </th>
+      <th>
+        Start date
+      </th>
+      <th>
+        End date
+      </th>
+      <th>
+        Misc
+      </th>
+    </tr>
+  </thead>
+  <tbody class="single">
+    ¤rows¤
+  </tbody>
+</table>
+
+¤¤ product_loan_table_row ¤¤
+<tr>
+  <td class="status ¤status¤">
+  </td>
+  <td>
+    ¤name¤
+  </td>
+  <td>
+    ¤start_date¤
+  </td>
+  <td>
+    ¤end_date¤
+  </td>
+  <td>
+    ¤note¤
+  </td>
+</tr>
+
+¤¤ public_user_details ¤¤
+<div id="public-message" class="¤hidden¤">
+  ¤message¤
+</div>
+<div id="public-active-loans">
+  <h2>Current loans</h2>
+  ¤active_loans¤
+</div>
+<div id="public-inactive-loans">
+  <h2>Old loans</h2>
+  ¤inactive_loans¤
+</div>
+
+¤¤ public_loan_table ¤¤
+<table class="history">
+  <thead>
+    <tr>
+      <th class="status">
+      </th>
+      <th>
+        Product
+      </th>
+      <th>
+        Serial number
+      </th>
+      <th>
+        Start date
+      </th>
+      <th>
+        End date
+      </th>
+    </tr>
+  </thead>
+  <tbody class="single">
+    ¤rows¤
+  </tbody>
+</table>
+
+¤¤ public_loan_table_row ¤¤
+<tr>
+  <td class="status ¤status¤">
+  </td>
+  <td>
+    ¤name¤
+  </td>
+  <td>
+    ¤serial¤
+  </td>
+  <td>
+    ¤start_date¤
+  </td>
+  <td>
+    ¤end_date¤
+  </td>
+</tr>
+
 ¤¤ loan_extend_form ¤¤
 <button onClick="JavaScript:showExtend(event)">
   Extend
diff --git a/html/sv/fragments.html b/html/sv/fragments.html
index db21515..0b0d8b6 100644
--- a/html/sv/fragments.html
+++ b/html/sv/fragments.html
@@ -626,14 +626,17 @@
   ¤inactive_loans¤
 </div>
 
-¤¤ loan_table ¤¤
+¤¤ user_loan_table ¤¤
 <table class="history">
   <thead>
     <tr>
       <th class="status">
       </th>
       <th>
-        ¤item¤
+        Artikel
+      </th>
+      <th>
+        Serienummer
       </th>
       <th>
         Startdatum
@@ -651,12 +654,15 @@
   </tbody>
 </table>
 
-¤¤ loan_table_row ¤¤
+¤¤ user_loan_table_row ¤¤
 <tr>
   <td class="status ¤status¤">
   </td>
   <td>
-    ¤item_link¤
+    ¤name¤
+  </td>
+  <td>
+    ¤serial¤
   </td>
   <td>
     ¤start_date¤
@@ -669,6 +675,105 @@
   </td>
 </tr>
 
+¤¤ product_loan_table ¤¤
+<table class="history">
+  <thead>
+    <tr>
+      <th class="status">
+      </th>
+      <th>
+        Låntagare
+      </th>
+      <th>
+        Startdatum
+      </th>
+      <th>
+        Slutdatum
+      </th>
+      <th>
+        Övrigt
+      </th>
+    </tr>
+  </thead>
+  <tbody class="single">
+    ¤rows¤
+  </tbody>
+</table>
+
+¤¤ product_loan_table_row ¤¤
+<tr>
+  <td class="status ¤status¤">
+  </td>
+  <td>
+    ¤name¤
+  </td>
+  <td>
+    ¤start_date¤
+  </td>
+  <td>
+    ¤end_date¤
+  </td>
+  <td>
+    ¤note¤
+  </td>
+</tr>
+
+¤¤ public_user_details ¤¤
+<div id="public-message" class="¤hidden¤">
+  ¤message¤
+</div>
+<div id="active-loans">
+  <h2>Aktuella lån</h2>
+  ¤active_loans¤
+</div>
+<div id="inactive-loans">
+  <h2>Gamla lån</h2>
+  ¤inactive_loans¤
+</div>
+
+¤¤ public_loan_table ¤¤
+<table class="history">
+  <thead>
+    <tr>
+      <th class="status">
+      </th>
+      <th>
+        Artikel
+      </th>
+      <th>
+        Serienummer
+      </th>
+      <th>
+        Startdatum
+      </th>
+      <th>
+        Slutdatum
+      </th>
+    </tr>
+  </thead>
+  <tbody class="single">
+    ¤rows¤
+  </tbody>
+</table>
+
+¤¤ public_loan_table_row ¤¤
+<tr>
+  <td class="status ¤status¤">
+  </td>
+  <td>
+    ¤name¤
+  </td>
+  <td>
+    ¤serial¤
+  </td>
+  <td>
+    ¤start_date¤
+  </td>
+  <td>
+    ¤end_date¤
+  </td>
+</tr>
+
 ¤¤ loan_extend_form ¤¤
 <button onClick="JavaScript:showExtend(event)">
   Förläng
diff --git a/include/Page.php b/include/Page.php
index 56920d5..66b0d71 100644
--- a/include/Page.php
+++ b/include/Page.php
@@ -222,15 +222,15 @@ abstract class Page extends Responder {
                 $end = $loan->get_endtime();
             }
             $rows .= replace(array('status' => $status,
-                                   'item_link' => $prodlink,
+                                   'name' => $prodlink,
+                                   'serial' => $product->get_serial(),
                                    'start_date' => format_date($start),
                                    'end_date' => format_date($end),
                                    'note' => $note),
-                             $this->fragments['loan_table_row']);
+                             $this->fragments['user_loan_table_row']);
         }
-        return replace(array('rows' => $rows,
-                             'item' => i18n('Product')),
-                       $this->fragments['loan_table']);
+        return replace(array('rows' => $rows),
+                       $this->fragments['user_loan_table']);
     }
 
     final protected function build_seen_table($products, $inventory) {
diff --git a/include/ProductPage.php b/include/ProductPage.php
index 6c4ca12..1933c95 100644
--- a/include/ProductPage.php
+++ b/include/ProductPage.php
@@ -129,15 +129,14 @@ class ProductPage extends Page {
                 }
             }
             $rows .= replace(array('status' => $status,
-                                   'item_link' => $itemlink,
+                                   'name' => $itemlink,
                                    'start_date' => format_date($start),
                                    'end_date' => format_date($end),
                                    'note' => $note),
-                             $this->fragments['loan_table_row']);
+                             $this->fragments['product_loan_table_row']);
         }
-        return replace(array('rows' => $rows,
-                             'item' => i18n('Borrower')),
-                       $this->fragments['loan_table']);
+        return replace(array('rows' => $rows),
+                       $this->fragments['product_loan_table']);
     }
 
 
diff --git a/include/PublicPage.php b/include/PublicPage.php
new file mode 100644
index 0000000..92cd4d4
--- /dev/null
+++ b/include/PublicPage.php
@@ -0,0 +1,77 @@
+<?php
+class PublicPage extends Page {
+    public function __construct() {
+        parent::__construct();
+
+        $user = explode('@', $_SERVER['REMOTE_USER'])[0];
+        try {
+            $this->user = new User($user, 'name');
+        } catch(Exception $ue) {
+            $this->user = User::create_user($user);
+        }
+        $this->subtitle = i18n("Hardware loans for {user}",
+                               $this->user->get_displayname($this->ldap));
+
+        // The public page should not display a menu
+        $this->menuitems = array();
+    }
+
+    protected function render_body() {
+        print($this->build_user_details());
+    }
+
+    protected function build_user_details() {
+        $message = '';
+        $hidden = 'hidden';
+        $active_loans = $this->user->get_loans('active');
+        $table_active = i18n('No active loans.');
+        if($active_loans) {
+            $table_active = $this->build_public_loan_table($active_loans);
+        }
+        $inactive_loans = $this->user->get_loans('inactive');
+        $table_inactive = i18n('No past loans.');
+        if($inactive_loans) {
+            $table_inactive = $this->build_public_loan_table($inactive_loans);
+        }
+
+        $overdue_count = count(array_filter($active_loans, function($loan) {
+            return $loan->is_overdue();
+        }));
+        if($overdue_count > 0) {
+            $message = i18n("You have {count} overdue loans.",
+                            $overdue_count);
+        }
+        if($message) {
+            $hidden = '';
+        }
+
+        return replace(array('message' => $message,
+                             'hidden' => $hidden,
+                             'active_loans' => $table_active,
+                             'inactive_loans' => $table_inactive),
+                       $this->fragments['public_user_details']);
+
+    }
+
+    protected function build_public_loan_table($loans) {
+        $rows = '';
+        foreach($loans as $loan) {
+            $product = $loan->get_product();
+            $start = $loan->get_starttime();
+            $end = $loan->get_returntime();
+            if(!$end) {
+                $end = $loan->get_endtime();
+            }
+            $rows .= replace(array('status' => $loan->get_status(),
+                                   'name' => $product->get_name(),
+                                   'serial' => $product->get_serial(),
+                                   'start_date' => format_date($start),
+                                   'end_date' => format_date($end)),
+                             $this->fragments['public_loan_table_row']);
+        }
+        return replace(array('rows' => $rows),
+                       $this->fragments['public_loan_table']);
+
+    }
+}
+?>
diff --git a/include/functions.php b/include/functions.php
index a975f29..909f55e 100644
--- a/include/functions.php
+++ b/include/functions.php
@@ -108,6 +108,8 @@ function make_page($page) {
             return new Printer();
         case 'dl':
             return new Download();
+        case 'public':
+            return new PublicPage();
     }
 }
 
diff --git a/include/translations.php b/include/translations.php
index a34cf90..5b0d0b8 100644
--- a/include/translations.php
+++ b/include/translations.php
@@ -453,6 +453,38 @@ $i18n = array(
             return "Service kan inte registreras på den här artikeln nu.";
         },
     ),
+    "You have {count} overdue loans." => array(
+        "en" => function($count) {
+            $loans = 'loans';
+            $products = 'products';
+            if($count == 1) {
+                $loans = 'loan';
+                $products = 'product';
+            }
+            return "You have $count overdue $loans. "
+                  ."Please return the $products as soon as possible "
+                  ."or have the $loans extended.";
+        },
+        "sv" => function($count) {
+            $late = 'försenade';
+            $products = 'artiklar';
+            $theproducts = 'artiklarna';
+            $theloans = 'lånen';
+            if($count == 1) {
+                $late = 'försenat';
+                $products = 'artikel';
+                $theproducts = 'artikeln';
+                $theloans = 'lånet';
+            }
+            return "Du har $count $late lån. "
+                  ."Vänligen lämna tillbaka $theproducts så snart som "
+                  ."möjligt eller förläng $theloans.";
+        },
+    ),
+    "Hardware loans for {user}" => array(
+        "en" => function($user) { return "Hardware loans for $user"; },
+        "sv" => function($user) { return "Hårdvarulån för $user"; },
+    ),
     /*
     "" => array(
         "en" => function() { return ""; },
diff --git a/style.css b/style.css
index bf7a753..fb253cd 100644
--- a/style.css
+++ b/style.css
@@ -213,6 +213,10 @@ h1 {
     grid-area: fourth;
 }
 
+#public-message {
+    grid-area: first / first / second / second;
+}
+
 #product-checkout {
     grid-area: third;
 }