summaryrefslogtreecommitdiff
path: root/views
diff options
context:
space:
mode:
authorRoger Rehnelt <noreply@maennchen1.de>2026-10-03 15:54:38 +0200
committerRoger Rehnelt <noreply@maennchen1.de>2026-10-03 15:54:38 +0200
commit578c435846e3195688104776b92253752b63ea8a (patch)
treefbbf8956e07af5e4470b925ac413781cfb897842 /views
parentf786f0c59d9a95d6829aaf58d99c882a609355ed (diff)
Widerrufsformular: Schutz vor Massenabsendungen, Liste nicht zugeordneter Widerrufe
Bot-Feld und Drosselung auf fünf Absendungen je Absender und Stunde (S21). Nicht zugeordnete Widerrufe stehen in den Moduleinstellungen und lassen sich löschen (S20). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'views')
-rw-r--r--views/mods/mod_revocation/ajaxDialogContent.phtml6
-rw-r--r--views/mods/mod_revocation/page_form.phtml6
-rw-r--r--views/mods/mod_revocation/settings_edit.phtml40
-rw-r--r--views/mods/mod_revocation/wpsg_revocation.css2
4 files changed, 54 insertions, 0 deletions
diff --git a/views/mods/mod_revocation/ajaxDialogContent.phtml b/views/mods/mod_revocation/ajaxDialogContent.phtml
index e10202c..960dc20 100644
--- a/views/mods/mod_revocation/ajaxDialogContent.phtml
+++ b/views/mods/mod_revocation/ajaxDialogContent.phtml
@@ -138,6 +138,12 @@ $arReason = \wpsgRevocation\Revocation::getReasons();
<?php } ?>
+ <?php /* Bot-Falle (S21): für Menschen und Screenreader unsichtbar, nicht in der Tab-Reihenfolge */ ?>
+ <div class="wpsg_revocation_hp" aria-hidden="true">
+ <label class="label" for="wpsg_rvd_url"><?php echo __('Bitte leer lassen', 'wpsg'); ?></label>
+ <input type="text" id="wpsg_rvd_url" name="wpsg_revocation_reason[url]" value="" tabindex="-1" autocomplete="off" />
+ </div>
+
<div class="form_field">
<label class="label" for="wpsg_rvd_name"><?php echo __('Name', 'wpsg'); ?></label>
<div class="value">
diff --git a/views/mods/mod_revocation/page_form.phtml b/views/mods/mod_revocation/page_form.phtml
index f76b2b8..1dfcbc9 100644
--- a/views/mods/mod_revocation/page_form.phtml
+++ b/views/mods/mod_revocation/page_form.phtml
@@ -87,6 +87,12 @@
</fieldset>
+ <?php /* Bot-Falle (S21): für Menschen und Screenreader unsichtbar, nicht in der Tab-Reihenfolge */ ?>
+ <div class="wpsg_revocation_hp" aria-hidden="true">
+ <label class="label" for="wpsg_rvp_url"><?php echo \__('Bitte leer lassen', 'wpsg'); ?></label>
+ <input type="text" id="wpsg_rvp_url" name="wpsg_revocation_reason[url]" value="" tabindex="-1" autocomplete="off" />
+ </div>
+
<div class="form_field">
<label class="label" for="wpsg_rvp_name"><?php echo \__('Name', 'wpsg'); ?></label>
<div class="value">
diff --git a/views/mods/mod_revocation/settings_edit.phtml b/views/mods/mod_revocation/settings_edit.phtml
index ee771eb..835535f 100644
--- a/views/mods/mod_revocation/settings_edit.phtml
+++ b/views/mods/mod_revocation/settings_edit.phtml
@@ -19,6 +19,7 @@
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" :class="{ 'active': tab === 1 }"><a href="#tab1" @click.prevent.stop="tab = 1"><?php echo __('Einstellungen', 'wpsg'); ?></a></li>
<li role="presentation" :class="{ 'active': tab === 2 }"><a href="#tab2" @click.prevent.stop="tab = 2"><?php echo __('Gründe für Retouren', 'wpsg'); ?></a></li>
+ <li role="presentation" :class="{ 'active': tab === 3 }"><a href="#tab3" @click.prevent.stop="tab = 3"><?php echo __('Nicht zugeordnete Widerrufe', 'wpsg'); ?></a></li>
</ul>
<input type="hidden" name="wpsg_mod_revocation_reason" v-model="jsonString" />
@@ -69,6 +70,45 @@
<a href="#" @click.prevent.stop="addReason" class="addReason"><span class="wpsg-glyphicon glyphicon glyphicon-plus"></span><?php echo __('Neuen Grund anlegen', 'wpsg'); ?></a>
</div>
+ <div v-show="tab === 3" class="tab-pane active">
+ <?php /* S20: Widerrufe ohne passende Bestellung; v-pre, damit eingetragene Texte keine Vue-Vorlage sind. Löschen über das Modulformular (POST, Nonce, wpsg_conf) */ $arUnassigned = \wpsgRevocation\Revocation::unassignedEntries(); ?>
+ <div v-pre class="wpsg_mod_revocation_unassigned">
+ <p><?php echo esc_html(wpsg_translate(__('Widerrufe, zu denen keine Bestellung oder Position gefunden wurde. Gespeichert werden höchstens die letzten #1#.', 'wpsg'), \wpsgRevocation\Revocation::UNASSIGNED_MAX)); ?></p>
+ <?php if (sizeof($arUnassigned) === 0) { ?>
+ <p><?php echo esc_html__('Keine Einträge.', 'wpsg'); ?></p>
+ <?php } else { ?>
+ <?php /* Der Admin-Controller speichert nur mit „submit“; auch die Löschknöpfe gehen diesen Weg (Nonce, wpsg_conf) */ ?>
+ <input type="hidden" name="submit" value="1" />
+ <table class="table">
+ <thead><tr>
+ <th scope="col"><?php echo esc_html__('Datum', 'wpsg'); ?></th>
+ <th scope="col"><?php echo esc_html__('Name', 'wpsg'); ?></th>
+ <th scope="col"><?php echo esc_html__('E-Mail', 'wpsg'); ?></th>
+ <th scope="col"><?php echo esc_html__('Bestellnummer', 'wpsg'); ?></th>
+ <th scope="col"><?php echo esc_html__('Artikelnummer', 'wpsg'); ?></th>
+ <th scope="col"><?php echo esc_html__('Menge', 'wpsg'); ?></th>
+ <th scope="col"><?php echo esc_html__('Vermerk', 'wpsg'); ?></th>
+ <th scope="col"><span class="screen-reader-text"><?php echo esc_html__('Löschen', 'wpsg'); ?></span></th>
+ </tr></thead>
+ <tbody>
+ <?php foreach (array_reverse($arUnassigned) as $entry) { ?>
+ <tr>
+ <td><?php echo esc_html(\mysql2date('d.m.Y H:i', (string)($entry['time']??''))); ?></td>
+ <td><?php echo esc_html((string)($entry['name']??'')); ?></td>
+ <td><?php echo esc_html((string)($entry['contact']??'')); ?></td>
+ <td><?php echo esc_html((string)($entry['order_nr']??'')); ?></td>
+ <td><?php echo esc_html((string)($entry['product_nr']??'')); ?></td>
+ <td><?php echo intval($entry['amount']??0); ?></td>
+ <td><?php echo esc_html(implode(', ', \wpsgRevocation\Revocation::noteTexts((array)($entry['notes']??[])))); ?></td>
+ <td><button type="submit" class="button" name="wpsg_mod_revocation_unassigned_delete" value="<?php echo esc_attr($entry['id']); ?>"><?php echo esc_html__('Löschen', 'wpsg'); ?></button></td>
+ </tr>
+ <?php } ?>
+ </tbody>
+ </table>
+ <button type="submit" class="button" name="wpsg_mod_revocation_unassigned_delete" value="all" onclick="return confirm(<?php echo esc_attr(wp_json_encode(__('Alle nicht zugeordneten Widerrufe löschen?', 'wpsg'))); ?>);"><?php echo esc_html__('Alle löschen', 'wpsg'); ?></button>
+ <?php } ?>
+ </div>
+ </div>
</div>
</div>
diff --git a/views/mods/mod_revocation/wpsg_revocation.css b/views/mods/mod_revocation/wpsg_revocation.css
index aae1758..5fe4b7d 100644
--- a/views/mods/mod_revocation/wpsg_revocation.css
+++ b/views/mods/mod_revocation/wpsg_revocation.css
@@ -53,6 +53,8 @@
#wpsg_revocation_form legend, #wpsg_revocation_page_form legend { padding:0 0.3684em; font-size:0.95em; font-weight:600; }
#wpsg_revocation_form .form_field, #wpsg_revocation_page_form .form_field { display:flex; flex-direction:column; gap:0.3em; width:100%; }
#wpsg_revocation_form .form_field .label, #wpsg_revocation_page_form .form_field .label { color:inherit; font-size:0.85em; opacity:0.7; }
+/* Bot-Falle (S21): aus dem Bild, ohne display:none, damit Programme sie ausfüllen */
+.wpsg_revocation_hp { position:absolute; left:-10000px; top:auto; width:1px; height:1px; overflow:hidden; }
/* Links in Schriftfarbe: Die Linkfarbe des Themes ist auf dem Dialog sonst zu blass (W5) */
#wpsg_revocation_dialog .inner a, .wpsg_revocation_page a { color:inherit; text-decoration:underline; }
#wpsg_revocation_form .form_field .value, #wpsg_revocation_page_form .form_field .value { display:flex; gap:0.5em; justify-content:stretch; }