diff options
Diffstat (limited to 'views/mods/mod_revocation')
| -rw-r--r-- | views/mods/mod_revocation/ajaxDialogContent.phtml | 148 | ||||
| -rwxr-xr-x | views/mods/mod_revocation/mail_row.phtml | 15 | ||||
| -rwxr-xr-x | views/mods/mod_revocation/mail_row_html.phtml | 24 | ||||
| -rw-r--r-- | views/mods/mod_revocation/mails/mail_admin_html.phtml | 80 | ||||
| -rw-r--r-- | views/mods/mod_revocation/mails/mail_admin_text.phtml | 44 | ||||
| -rw-r--r-- | views/mods/mod_revocation/mails/mail_customer_html.phtml | 75 | ||||
| -rw-r--r-- | views/mods/mod_revocation/mails/mail_customer_text.phtml | 53 | ||||
| -rw-r--r-- | views/mods/mod_revocation/order_view_row.phtml | 19 | ||||
| -rw-r--r-- | views/mods/mod_revocation/produkt_edit_allgemein.phtml | 16 | ||||
| -rw-r--r-- | views/mods/mod_revocation/settings_edit.phtml | 121 | ||||
| -rw-r--r-- | views/mods/mod_revocation/wp_footer.phtml | 331 | ||||
| -rw-r--r-- | views/mods/mod_revocation/wpsg_mod_kundenverwaltung_order_after_products.phtml | 49 | ||||
| -rw-r--r-- | views/mods/mod_revocation/wpsg_producttemplate_afterButton.phtml | 25 | ||||
| -rw-r--r-- | views/mods/mod_revocation/wpsg_revocation.css | 58 | ||||
| -rw-r--r-- | views/mods/mod_revocation/wpsg_revocation.js | 0 |
15 files changed, 1058 insertions, 0 deletions
diff --git a/views/mods/mod_revocation/ajaxDialogContent.phtml b/views/mods/mod_revocation/ajaxDialogContent.phtml new file mode 100644 index 0000000..e833a00 --- /dev/null +++ b/views/mods/mod_revocation/ajaxDialogContent.phtml @@ -0,0 +1,148 @@ +<?php + + declare(strict_types=1); + + /** + * @author: Daniel Schmitzer + * @date: 10.04.26 + * @time: 09:10 + */ + + namespace wpsgRevocation; + + use \wpsg\M1; + use wpsg_product; + + $arReason = \wpsgRevocation\Revocation::getReasons(); + + // Produkte + $dialog_config = json_decode((wp_kses_stripslashes($_REQUEST['dialog_config']??'[]')), true); + + $contact_email = ""; + + $customer_login_id = intval(\wpsg_ShopController::getShop()->callMod('wpsg_mod_kundenverwaltung', 'isLoggedIn')); + + if ($customer_login_id > 0) { + + $oCustomer = \wpsg_customer::getInstance($customer_login_id); + + $contact_email = $oCustomer->getEmail(); + + } + +?> + +<form id="wpsg_revocation_form" class="wpsg"> + + <div id="msg_target"></div> + + <?php if (sizeof($dialog_config['arOrderProductID']) > 0) { ?> + + <?php foreach ($dialog_config['arOrderProductID'] as $row) { + + $order_id = intval($row['order_id']); + $order_product_id = intval($row['order_product_id']); + $amount = intval($row['amount']); + + $oOrder = \wpsg_order::getInstance($order_id); + $oOrderProduct = \wpsg_order_product::getInstance($order_product_id); + + if (!$oOrder->isLoaded() || !$oOrderProduct->isLoaded()) continue; + + $key = $order_id.'_'.$order_product_id; + + ?> + + <fieldset class="wpsg_revocation_order_product"> + <legend><?php echo $oOrderProduct->getProduct()->getProductName(); ?></legend> + <div> + + <input type="hidden" readonly name="wpsg_revocation_reason[row][<?php echo $key; ?>][order_product_id]" value="<?php echo $oOrderProduct->getId(); ?>" /> + + <div class="form_field"> + <div class="label"><?php echo __('Bestellnummer / Menge', 'wpsgRevocation'); ?></div> + <div class="value"> + <input type="text" readonly name="wpsg_revocation_reason[row][<?php echo $key; ?>][order_nr]" value="<?php echo $oOrder->getNr(); ?>" /> + <input type="number" min="1" max="<?php echo $amount; ?>" name="wpsg_revocation_reason[row][<?php echo $key; ?>][amount]" value="<?php echo $amount; ?>" /> + </div> + </div> + + <div class="form_field"> + <div class="label"><?php echo __('Widerrufsgrund', 'wpsgRevocation'); ?></div> + <div class="value"> + <select name="wpsg_revocation_reason[row][<?php echo $key; ?>][reason]" required> + <option value=""><?php echo __('Bitte einen Grund auswählen', 'wpsgRevocation'); ?></option> + <?php foreach ($arReason as $reason) { ?> + <option value="<?php echo htmlspecialchars($reason['id']); ?>"><?php echo htmlspecialchars($reason['text']); ?></option> + <?php } ?> + </select> + </div> + </div> + + <div class="form_field"> + <div class="label"><?php echo __('Bemerkung', 'wpsgRevocation'); ?></div> + <div class="value"> + <textarea name="wpsg_revocation_reason[row][<?php echo $key; ?>][comment]"></textarea> + </div> + </div> + + </div> + </fieldset> + + <?php } ?> + + <?php } else { + + $key = 0; + + ?> + + <fieldset class="wpsg_revocation_order_product"> + + <div class="form_field"> + <div class="label"><?php echo __('Produkt - Nr.', 'wpsgRevocation'); ?></div> + <div class="value"> + <input type="text" name="wpsg_revocation_reason[row][<?php echo $key; ?>][product_nr]" value="<?php echo ($dialog_config['set_product_anr']??''); ?>" /> + </div> + </div> + + <div class="form_field"> + <div class="label"><?php echo __('Bestellnummer / Menge', 'wpsgRevocation'); ?></div> + <div class="value"> + <input type="text" name="wpsg_revocation_reason[row][<?php echo $key; ?>][order_nr]" value="" /> + <input type="number" name="wpsg_revocation_reason[row][<?php echo $key; ?>][amount]" value="1" /> + </div> + </div> + + <div class="form_field"> + <div class="label"><?php echo __('Widerrufsgrund', 'wpsgRevocation'); ?></div> + <div class="value"> + <select name="wpsg_revocation_reason[row][<?php echo $key; ?>][reason]"> + <?php foreach ($arReason as $reason) { ?> + <option value="<?php echo htmlspecialchars($reason['id']); ?>"><?php echo htmlspecialchars($reason['text']); ?></option> + <?php } ?> + </select> + </div> + </div> + + <div class="form_field"> + <div class="label"><?php echo __('Bemerkung', 'wpsgRevocation'); ?></div> + <div class="value"> + <textarea name="wpsg_revocation_reason[row][<?php echo $key; ?>][comment]"></textarea> + </div> + </div> + + </fieldset> + + <?php } ?> + + <div class="form_field"> + <div class="label"><?php echo __('Kontakt - E-Mail', 'wpsgRevocation'); ?></div> + <div class="value"> + <input type="email" required name="wpsg_revocation_reason[contact]" value="<?php echo $contact_email; ?>" + <?php echo (($contact_email !== '')?'readonly':''); ?> + /> + </div> + </div> + +</form>
\ No newline at end of file diff --git a/views/mods/mod_revocation/mail_row.phtml b/views/mods/mod_revocation/mail_row.phtml new file mode 100755 index 0000000..8a54f89 --- /dev/null +++ b/views/mods/mod_revocation/mail_row.phtml @@ -0,0 +1,15 @@ +<?php + + /** + * Template für die Integration des Widerruflinks in die Kunden- und Adminmail + */ + + $order_id = intval($this->view['order_id']); + $order_nr = $this->view['wpsg_mod_revocation']['order_nr']; + $product_nr = $this->view['wpsg_mod_revocation']['product_nr']; + $amount = $this->view['wpsg_mod_revocation']['amount']; + $order_product_id = intval($this->view['order_product_id']); + + $revo_url = get_home_url('/', '', 'http').'?wpsg_revo_order='.urlencode($order_nr).'&wpsg_revo_product='.urlencode($product_nr).'&wpsg_revo_amount='.urlencode($amount); + +?><?php echo wpsg_pad_left(__('Widerruf:', 'wpsgRevocation').' ', 15); ?> <?php echo $revo_url; ?>
\ No newline at end of file diff --git a/views/mods/mod_revocation/mail_row_html.phtml b/views/mods/mod_revocation/mail_row_html.phtml new file mode 100755 index 0000000..e7f2945 --- /dev/null +++ b/views/mods/mod_revocation/mail_row_html.phtml @@ -0,0 +1,24 @@ +<?php + + /** + * Template für die Integration des Widerruflinks in die Kunden- und Adminmail (HTML) + */ + + $i = intval($this->view['i']); + + $order_id = intval($this->view['order_id']); + $order_nr = $this->view['wpsg_mod_revocation']['order_nr']; + $product_nr = $this->view['wpsg_mod_revocation']['product_nr']; + $amount = $this->view['wpsg_mod_revocation']['amount']; + $order_product_id = intval($this->view['order_product_id']); + + $revo_url = get_home_url('/', '', 'http').'?wpsg_revo_order='.urlencode($order_nr).'&wpsg_revo_product='.urlencode($product_nr).'&wpsg_revo_amount='.urlencode($amount); + +?> +<tr class="productrow productrow2 <?php echo ((($i % 2) == 0)?'productrow_odd':'productrow_even'); ?>"> + <td style="padding:4px; line-height:100%; vertical-align:middle;" class="col_pos"> </td> + <td style="padding:4px; line-height:100%; vertical-align:middle;" class="col_name"><?php echo __('Widerruf', 'wpsgRevocation'); ?>:</td> + <td style="padding:4px; line-height:100%; vertical-align:middle;" class="col_name" colspan="4"> + <a href="<?php echo $revo_url; ?>"><?php echo __('Widerruf starten', 'wpsgRevocation'); ?></a> + </td> +</tr> diff --git a/views/mods/mod_revocation/mails/mail_admin_html.phtml b/views/mods/mod_revocation/mails/mail_admin_html.phtml new file mode 100644 index 0000000..57920b5 --- /dev/null +++ b/views/mods/mod_revocation/mails/mail_admin_html.phtml @@ -0,0 +1,80 @@ +<?php + + declare(strict_types=1); + + /** + * @author: Daniel Schmitzer + * @date: 14.04.26 + * @time: 09:21 + */ + + namespace wpsgRevocation; + + $arSubmitData = \wpsg_ShopController::getShop()->view['arSubmitData'] ?? []; + $arReason = Revocation::getReasons(); + +?> +<p><?php echo __('Hallo,', 'wpsgRevocation'); ?></p> + +<p><?php echo __('ein Kunde hat einen Widerruf für ein Produkt durchgeführt.', 'wpsgRevocation'); ?></p> + +<p> + <strong><?php echo __('Name', 'wpsgRevocation'); ?>:</strong> %kunde_anrede% %kunde_vname% %kunde_name%<br> + <strong><?php echo __('E-Mail', 'wpsgRevocation'); ?>:</strong> %kunde_email% +</p> + +<hr> + +<?php foreach ($arSubmitData as $key => $d): + + $oOrder = $d['oOrder']; + $oOrderProduct = $d['oOrderProduct']; + + $reasonText = array_values(array_filter( + $arReason, + function($item) use ($d) { + return $item['id'] === $d['reason']; + } + ))[0]['text'] ?? ''; +?> + + <div style="margin-bottom:15px; padding-bottom:10px; border-bottom:1px solid #ddd;"> + <p> + <strong><?php echo __('Bestellung', 'wpsgRevocation'); ?>:</strong> + <?php echo $oOrder->getNr(); ?> + </p> + + <p> + <strong><?php echo __('Produkt', 'wpsgRevocation'); ?>:</strong> + <?php echo $d['amount']; ?> x <?php echo $oOrderProduct->getProduct()->getProductName(true); ?> + / <?php echo __('Artikelnummer', 'wpsgRevocation'); ?>: + <?php echo $oOrderProduct->getProduct()->getNr(); ?> + </p> + + <p> + <strong><?php echo __('Ausgewählter Grund', 'wpsgRevocation'); ?>:</strong> + <?php echo $reasonText; ?> + </p> + + <p> + <strong><?php echo __('Bemerkung', 'wpsgRevocation'); ?>:</strong> + <?php echo nl2br(htmlspecialchars($d['comment'] ?? '')); ?> + </p> + </div> + +<?php endforeach; ?> + +<p> + <strong><?php echo __('Datum des Widerrufs', 'wpsgRevocation'); ?>:</strong> + <?php echo date('d.m.Y H:i:s'); ?> +</p> + +<p> + <?php echo __('Bitte prüft den Vorgang und führt die Rückabwicklung (Storno / Rückerstattung) durch.', 'wpsgRevocation'); ?> +</p> + +<p> + <?php echo __('Viele Grüße', 'wpsgRevocation'); ?><br> + <?php echo __(\wpsg_ShopController::getShop()->get_option('wpsg_shopdata_name'), 'wpsgRevocation'); ?> + - <?php echo __('Team', 'wpsgRevocation'); ?> +</p>
\ No newline at end of file diff --git a/views/mods/mod_revocation/mails/mail_admin_text.phtml b/views/mods/mod_revocation/mails/mail_admin_text.phtml new file mode 100644 index 0000000..8ce601a --- /dev/null +++ b/views/mods/mod_revocation/mails/mail_admin_text.phtml @@ -0,0 +1,44 @@ +<?php + + declare(strict_types=1); + + /** + * @author: Daniel Schmitzer + * @date: 14.04.26 + * @time: 09:21 + */ + + namespace wpsgRevocation; + + $arSubmitData = \wpsg_ShopController::getShop()->view['arSubmitData'] ?? []; + $arReason = Revocation::getReasons(); + +?><?php echo __('Hallo,', 'wpsgRevocation'); ?> + +<?php echo __('ein Kunde hat einen Widerruf für ein Produkt durchgeführt.', 'wpsgRevocation'); ?> + +<?php echo mb_str_pad(__('Name', 'wpsgRevocation').':', 25); ?> %kunde_anrede% %kunde_vname% %kunde_name% +<?php echo mb_str_pad(__('E-Mail', 'wpsgRevocation').':', 25); ?> %kunde_email% + +<?php foreach ($arSubmitData as $key => $d) { + + /** @var \wpsg_order $oOrder */ + $oOrder = $d['oOrder']; + + /** @var \wpsg_order_product $oOrderProduct */ + $oOrderProduct = $d['oOrderProduct']; + +?> +<?php echo mb_str_pad(__('Bestellung', 'wpsgRevocation').':', 25); ?> <?php echo $oOrder->getNr(); ?> +<?php echo mb_str_pad(__('Produkt', 'wpsgRevocation').':', 25); ?> <?php echo $d['amount']; ?> x <?php echo $oOrderProduct->getProduct()->getProductName(true); ?> / <?php echo __('Artikelnummer', 'wpsgRevocation'); ?>: <?php echo $oOrderProduct->getProduct()->getNr(); ?> +<?php echo mb_str_pad(__('Ausgewählter Grund', 'wpsgRevocation').':', 25); ?> <?php echo array_values(array_filter($arReason, function($item) use ($d) { return $item['id'] === $d['reason']; }))[0]['text'] ?? ''; ?> +<?php echo mb_str_pad(__('Bemerkung', 'wpsgRevocation').':', 25); ?> <?php echo $d['comment']; ?> + +<?php } ?> + +<?php echo mb_str_pad(__('Datum des Widerrufs', 'wpsgRevocation').':', 25); ?> <?php echo date('d.m.Y H:i:s'); ?> + +<?php echo __('Bitte prüft den Vorgang und führt die Rückabwicklung (Storno / Rückerstattung) durch.', 'wpsgRevocation'); ?> + +<?php echo __('Viele Grüße', 'wpsgRevocation'); ?> +<?php echo __(\wpsg_ShopController::getShop()->get_option('wpsg_shopdata_name'), 'wpsgRevocation'); ?> - <?php echo __('Team', 'wpsgRevocation'); ?>
\ No newline at end of file diff --git a/views/mods/mod_revocation/mails/mail_customer_html.phtml b/views/mods/mod_revocation/mails/mail_customer_html.phtml new file mode 100644 index 0000000..f946efa --- /dev/null +++ b/views/mods/mod_revocation/mails/mail_customer_html.phtml @@ -0,0 +1,75 @@ +<?php + + declare(strict_types=1); + + /** + * @author: Daniel Schmitzer + * @date: 14.04.26 + * @time: 09:21 + */ + + namespace wpsgRevocation; + + $arSubmitData = \wpsg_ShopController::getShop()->view['arSubmitData'] ?? []; + $arReason = Revocation::getReasons(); + +?> +<p><?php echo __('Hallo', 'wpsgRevocation'); ?> %kunde_anrede% %kunde_name%,</p> + +<p><?php echo __('wir haben Ihren Widerruf erhalten und bedanken uns für Ihre Mitteilung.', 'wpsgRevocation'); ?></p> + +<h3><?php echo __('Ihre Widerrufsanmeldung:', 'wpsgRevocation'); ?></h3> + +<?php foreach ($arSubmitData as $key => $d): + + $oOrder = $d['oOrder']; + $oOrderProduct = $d['oOrderProduct']; + + $reasonText = array_values(array_filter( + $arReason, + function($item) use ($d) { + return $item['id'] === $d['reason']; + } + ))[0]['text'] ?? ''; +?> + + <div style="margin-bottom:20px; padding:15px; background-color:#f9f9f9; border-radius:5px;"> + <p style="margin:0 0 10px 0;"> + <strong><?php echo __('Bestellnummer', 'wpsgRevocation'); ?>:</strong> + <?php echo $oOrder->getNr(); ?> + </p> + + <p style="margin:0 0 10px 0;"> + <strong><?php echo __('Produkt', 'wpsgRevocation'); ?>:</strong> + <?php echo $d['amount']; ?> x <?php echo $oOrderProduct->getProduct()->getProductName(true); ?> + / <?php echo __('Artikelnr.', 'wpsgRevocation'); ?>: + <?php echo $oOrderProduct->getProduct()->getNr(); ?> + </p> + + <p style="margin:0 0 10px 0;"> + <strong><?php echo __('Grund', 'wpsgRevocation'); ?>:</strong> + <?php echo $reasonText; ?> + </p> + + <?php if (!empty($d['comment'])): ?> + <p style="margin:0 0 10px 0;"> + <strong><?php echo __('Bemerkung', 'wpsgRevocation'); ?>:</strong> + <?php echo nl2br(htmlspecialchars($d['comment'])); ?> + </p> + <?php endif; ?> + </div> + +<?php endforeach; ?> + +<p> + <strong><?php echo __('Widerrufdatum', 'wpsgRevocation'); ?>:</strong> + <?php echo date('d.m.Y H:i:s'); ?> +</p> + +<p><?php echo __('Wir werden Ihren Widerruf nun schnellstmöglich bearbeiten und uns bei Fragen mit Ihnen in Verbindung setzen.', 'wpsgRevocation'); ?></p> + +<p> + <?php echo __('Mit freundlichen Grüßen', 'wpsgRevocation'); ?><br> + <?php echo \wpsg_ShopController::getShop()->get_option('wpsg_shopdata_name'); ?> + - <?php echo __('Team', 'wpsgRevocation'); ?> +</p>
\ No newline at end of file diff --git a/views/mods/mod_revocation/mails/mail_customer_text.phtml b/views/mods/mod_revocation/mails/mail_customer_text.phtml new file mode 100644 index 0000000..0608fc5 --- /dev/null +++ b/views/mods/mod_revocation/mails/mail_customer_text.phtml @@ -0,0 +1,53 @@ +<?php + + declare(strict_types=1); + + /** + * @author: Daniel Schmitzer + * @date: 14.04.26 + * @time: 09:21 + */ + + namespace wpsgRevocation; + + $arSubmitData = \wpsg_ShopController::getShop()->view['arSubmitData'] ?? []; + $arReason = Revocation::getReasons(); + +?><?php echo __('Hallo', 'wpsgRevocation'); ?> %kunde_anrede% %kunde_name%, + +<?php echo __('wir haben Ihren Widerruf erhalten und bedanken uns für Ihre Mitteilung.', 'wpsgRevocation'); ?> + +<?php echo __('Ihre Widerrufsanmeldung:', 'wpsgRevocation'); ?> + +<?php foreach ($arSubmitData as $key => $d): + + $oOrder = $d['oOrder']; + $oOrderProduct = $d['oOrderProduct']; + + $reasonText = array_values(array_filter( + $arReason, + function($item) use ($d) { + return $item['id'] === $d['reason']; + } + ))[0]['text'] ?? ''; +?> + +<?php echo mb_str_pad(__('Bestellnummer', 'wpsgRevocation').':', 20); ?> <?php echo $oOrder->getNr(); ?> + +<?php echo mb_str_pad(__('Produkt', 'wpsgRevocation').':', 20); ?> <?php echo $d['amount']; ?> x <?php echo $oOrderProduct->getProduct()->getProductName(true); ?> / <?php echo __('Artikelnr.', 'wpsgRevocation'); ?>: <?php echo $oOrderProduct->getProduct()->getNr(); ?> + +<?php echo mb_str_pad(__('Grund', 'wpsgRevocation').':', 20); ?> <?php echo $reasonText; ?> + +<?php if (!empty($d['comment'])): ?> +<?php echo mb_str_pad(__('Bemerkung', 'wpsgRevocation').':', 20); ?> <?php echo $d['comment']; ?> +<?php endif; ?> + +<?php endforeach; ?> + +<?php echo mb_str_pad(__('Widerrufdatum', 'wpsgRevocation').':', 20); ?> <?php echo date('d.m.Y H:i:s'); ?> + +<?php echo __('Wir werden Ihren Widerruf nun schnellstmöglich bearbeiten und uns bei Fragen mit Ihnen in Verbindung setzen.', 'wpsgRevocation'); ?> + +<?php echo __('Mit freundlichen Grüßen', 'wpsgRevocation'); ?> + +<?php echo \wpsg_ShopController::getShop()->get_option('wpsg_shopdata_name'); ?> - <?php echo __('Team', 'wpsgRevocation'); ?>
\ No newline at end of file diff --git a/views/mods/mod_revocation/order_view_row.phtml b/views/mods/mod_revocation/order_view_row.phtml new file mode 100644 index 0000000..8c95b5b --- /dev/null +++ b/views/mods/mod_revocation/order_view_row.phtml @@ -0,0 +1,19 @@ +<?php + + declare(strict_types=1); + + /** + * Integration eines Widerrufes in die Bestellansicht im Backend (Abo-Verlängerungen) + */ + + $row = $this->view['wpsg_mod_revocation']['row']??null; + + if ($row === null) return; + +?> +<tr class="wpsg_<?php echo (($this->view['i'] == 0)?'odd':'even'); ?>"> + <td colspan="5"> + <?php echo __('Widerruf', 'wpsgRevocation'); ?>: + <?php echo wpsg_translate(__('#1# Stück am #2# widerrufen', 'wpsgRevocation'), $row['amount'], \wp_date('d. F Y H:i:s', strtotime($row['time']))); ?> + </td> +</tr>
\ No newline at end of file diff --git a/views/mods/mod_revocation/produkt_edit_allgemein.phtml b/views/mods/mod_revocation/produkt_edit_allgemein.phtml new file mode 100644 index 0000000..42ff8ff --- /dev/null +++ b/views/mods/mod_revocation/produkt_edit_allgemein.phtml @@ -0,0 +1,16 @@ +<?php + + declare(strict_types=1); + + /** + * @author: Daniel Schmitzer + * @date: 27.05.26 + * @time: 14:42 + */ + + namespace wpsgRevocation; + + $oProduct = \wpsg_product::getInstance(intval($this->view['data']['id'])); + + echo wpsg_drawForm_Checkbox('wpsg_mod_revocation_disable', __('Widerrufsbutton nicht anzeigen', 'wpsg'), $oProduct->getMeta('wpsg_mod_revocation_disable', false, 0)); ?> +
\ No newline at end of file diff --git a/views/mods/mod_revocation/settings_edit.phtml b/views/mods/mod_revocation/settings_edit.phtml new file mode 100644 index 0000000..fbab6a1 --- /dev/null +++ b/views/mods/mod_revocation/settings_edit.phtml @@ -0,0 +1,121 @@ +<?php + + declare(strict_types=1); + + /** + * @author: Daniel Schmitzer + * @date: 14.04.26 + * @time: 06:32 + */ + + $arReason = \wpsgRevocation\Revocation::getReasons(); + +?> + +<div id="wpsg_mod_revocation_reason_wrap"> + <div id="wpsg_mod_revocation_reason_app"> + + <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', 'wpsgRevocation'); ?></a></li> + <li role="presentation" :class="{ 'active': tab === 2 }"><a href="#tab2" @click.prevent.stop="tab = 2"><?php echo __('Gründe für Retouren', 'wpsgRevocation'); ?></a></li> + </ul> + + <input type="hidden" name="wpsg_mod_revocation_reason" v-model="jsonString" /> + + <div class="tab-content"> + <div v-show="tab === 1" class="tab-pane active"> + + <?php echo wpsg_drawForm_Checkbox('wpsg_mod_revocation_view_order', __('An Produkten im Kundenfrontend an den Bestellungen anzeigen.', 'wpsgRevocation'), wpsg_ShopController::getShop()->get_option('wpsg_mod_revocation_view_order'), ['fullWidth' => true]); ?> + <?php echo wpsg_drawForm_Checkbox('wpsg_mod_revocation_view_flyout', __('Auf allen Seiten ein Widerrufs-Flyout anzeigen.', 'wpsgRevocation'), wpsg_ShopController::getShop()->get_option('wpsg_mod_revocation_view_flyout'), ['fullWidth' => true]); ?> + <?php echo wpsg_drawForm_Checkbox('wpsg_mod_revocation_view_product', __('Im Produkt neben "In den Warenkorb" anzeigen.', 'wpsgRevocation'), wpsg_ShopController::getShop()->get_option('wpsg_mod_revocation_view_product'), ['fullWidth' => true]); ?> + <?php echo wpsg_drawForm_Checkbox('wpsg_mod_revocation_view_customer_mail', __('Widerruflink in Bestellbestätigungsmail an Kunden.', 'wpsgRevocation'), wpsg_ShopController::getShop()->get_option('wpsg_mod_revocation_view_customer_mail'), ['fullWidth' => true]); ?> + + <p class="wpsg_note"> + <?php echo wpsg_translate( + __('Einstellungen zu den E-Mails finden Sie in der <a href="#1#">E-Mail Konfiguration</a>.', 'wpsgRevocation'), + WPSG_URL_WP.'wp-admin/admin.php?page=wpsg-Admin&subaction=emailconf' + ); ?><br /> + <?php echo __('Das Modul setzt eindeutige Artikelnummern voraus.', 'wpsgRevocation'); ?> + </p> + + </div> + <div v-show="tab === 2" class="tab-pane active"> + <div class="reason_wrap" v-if="arReason.length > 0"> + <template v-for="r of arReason"> + <div class="wpsg_form_field"> + <label class="label"><?php echo __('ID', 'wpsgRevocation'); ?></label> + <div class="value"> + {{r.id}} + <a data-id="1" class="removeReason" @click.prevent.stop="removeReason(r)" href="#"><span class="wpsg-glyphicon glyphicon glyphicon-trash"></span></a> + </div> + </div> + <div class="wpsg_form_field"> + <label class="label"><?php echo __('Text', 'wpsgRevocation'); ?></label> + <div class="value"> + <input type="text" v-model="r.text" /> + </div> + </div> + <hr /> + </template> + </div> + <p v-else><?php echo __('Keine Gründe definiert', 'wpsgRevocation'); ?></p> + + <a href="#" @click.prevent.stop="addReason" class="addReason"><span class="wpsg-glyphicon glyphicon glyphicon-plus"></span><?php echo __('Neuen Grund anlegen', 'wpsgRevocation'); ?></a> + </div> + </div> + + </div> +</div> + +<style> + + #wpsg_mod_revocation_reason_wrap { + .wpsg_note { margin-top:1rem; font-style:italic; } + .addReason { margin-top:1rem; display:block; } + .removeReason { position:absolute; right:0; top:7px; font-size:1.4rem; } + .wpsg_form_field { display:grid; grid-template-columns:100px 1fr; column-gap:2rem; row-gap:1rem; width:100%; align-items:center; position:relative; min-height:30px; + & > .label { font-weight:bold; display:block; padding:0; margin:0; color:black; font-size:100%; text-align:left; } + & > .value { + input { width:100%; } + } + } + } + +</style> + +<script type="module"> + + import { createApp, computed, ref } from '<?php echo wpsg_ShopController::getShop()->getRessourceURL('js/vue.esm-browser.prod.3.5.32.js'); ?>'; + + createApp({ + setup() { + + const tab = ref(1); + const arReason = ref(<?php echo json_encode($arReason); ?>); + + const addReason = () => { + + const id = Date.now().toString(36) + Math.random().toString(36).slice(2); + arReason.value.push({ text: '', id: id }); + + }; + const removeReason = r => { + + if (confirm('<?php echo __('Sind Sie sich sicher?', 'wpsgRevocation'); ?>')) { + + arReason.value = arReason.value.filter(v => v !== r); + + } + + } + + const jsonString = computed(() => JSON.stringify(arReason.value)); + + return { + addReason, removeReason, + arReason, jsonString, tab + }; + } + }).mount('#wpsg_mod_revocation_reason_app'); + +</script>
\ No newline at end of file diff --git a/views/mods/mod_revocation/wp_footer.phtml b/views/mods/mod_revocation/wp_footer.phtml new file mode 100644 index 0000000..3c0f225 --- /dev/null +++ b/views/mods/mod_revocation/wp_footer.phtml @@ -0,0 +1,331 @@ +<?php + + declare(strict_types=1); + + /** + * @author: Daniel Schmitzer + * @date: 27.01.26 + * @time: 09:26 + */ + + namespace wpsgRevocation; + +?> + +<?php if (\wpsg_ShopController::getShop()->get_option('wpsg_mod_revocation_view_flyout') === '1') { ?> + + <div id="wpsg_revocation_button"> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19,15V3H23V15H19M15,3A2,2 0 0,1 17,5V15C17,15.55 16.78,16.05 16.41,16.41L9.83,23L8.77,21.94C8.5,21.67 8.33,21.3 8.33,20.88L8.36,20.57L9.31,16H3C1.89,16 1,15.1 1,14V12C1,11.74 1.05,11.5 1.14,11.27L4.16,4.22C4.46,3.5 5.17,3 6,3H15M15,5H5.97L3,12V14H11.78L10.65,19.32L15,14.97V5Z" /></svg> + <span><?php echo __('Widerrufsformular', 'wpsgRevocation'); ?></span> + </div> + +<?php } else { ?> + + <div id="wpsg_revocation_button" style="display:none;"></div> + +<?php } ?> + +<!-- Dialog --> +<div id="wpsg_revocation_dialog" class=""> + <div class="inner"> + <div class="header"> + <span><?php echo __('Widerrufsformular', 'wpsgRevocation'); ?></span> + <a href="#" class="close"> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" /></svg> + </a> + </div> + <div class="content"></div> + <div class="footer"> + <button class="button button-primary wpsg_revocation_button_submit"><?php echo __('Abschicken', 'wpsgRevocation'); ?></button> + </div> + <div class="loading"> + <img src="<?php echo WPSG_URL; ?>views/gfx/ajax-loader.gif" alt="<?php echo __('Bitte warten ...', 'wpsgRevocation'); ?>" /> + </div> + </div> +</div> + +<script> + + console.log('ok'); + + const wpsg_revocation_nonce = '<?php echo wp_create_nonce('wpsg_mod_revocation_nonce'); ?>'; + const el_dialog = document.getElementById('wpsg_revocation_dialog'); + const el_dialog_content = document.getElementById('wpsg_revocation_dialog').querySelector('.inner > .content'); + + const formDataToObject = (formData) => { + + const obj = {}; + + for (const [key, value] of formData.entries()) { + + const keys = key.split(/\[|\]/).filter(Boolean); + let current = obj; + + keys.forEach((k, i) => { + + const isLast = i === keys.length - 1; + + if (isLast) { current[k] = value; } + else { + + if (!current[k]) { current[k] = isNaN(keys[i + 1]) ? {} : []; } + + current = current[k]; + + } + + }); + + } + + return obj; + + } + + const submit_dialog = event => { + + event.preventDefault(); + event.stopPropagation(); + + el_dialog.classList.add('loading'); + + // const form_data = Object.fromEntries(new FormData(el_dialog.querySelector('form#wpsg_revocation_form')).entries()); + const form = el_dialog.querySelector('form#wpsg_revocation_form'); + const formData = new FormData(form); + const form_data = formDataToObject(formData); + + fetch('<?php echo admin_url('admin-ajax.php'); ?>?action=wpsg_mod_revocation&do=ajaxDialogSubmit', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + nonce: wpsg_revocation_nonce, + form_data: form_data, + }) + }).then(res => res.json()).then(res => { + + let html = ''; + + if ((res.success??false) === false) { + + html += '<ul id="wpsg_error" class="wpsg_error">'; + (res.arError??[]).forEach(error => { html += `<li>${error}</li>`; }); + html += '</ul>'; + + el_dialog_content.querySelector('#msg_target').innerHTML = html; + + el_dialog.classList.remove('loading'); + + } else { + + alert('<?php echo __('Ihr Widerruf ist bei uns eingegangen und wird bearbeitet.', 'wpsgRevocation'); ?>'); + close_dialog(event); + + document.querySelectorAll('.wpsg_revocation_order_product_checkbox:checked').forEach(el => { + + el.checked = false; + + }); + + } + + }); + + } + const close_dialog = event => { + + event.preventDefault(); + event.stopPropagation(); + + el_dialog.classList.remove('visible'); + + }; + const open_dialog = el => { + + el_dialog.classList.toggle('visible'); + el_dialog.classList.add('loading'); + + const dialog_config = { + arProductID: [], + arOrderProductID: [], + set_product_anr: '' + } + + // Produkte auf der Seite + document.querySelectorAll('input[name="wpsg[produkt_id]"]').forEach(el => { dialog_config.arProductID.push(parseInt(el.value)); }) + + if (el !== undefined && el.classList.contains('wpsg_revocation_order_product')) { + + el.querySelector('input').checked = true; + + } + + if (el !== undefined && el.classList.contains('wpsg_revocation_product_button')) { + + dialog_config.set_product_anr = el.dataset.product_anr; + + } + + // Bestellung / Produkte + document.querySelectorAll('.wpsg_revocation_order_product_checkbox:checked').forEach(el => { + + const order_id = parseInt(el.dataset.order_id); + const order_product_id = parseInt(el.dataset.order_product_id); + const product_id = parseInt(el.dataset.product_id); + const amount = parseInt(el.dataset.amount); + + dialog_config.arOrderProductID.push({ + order_id: order_id, + order_product_id: order_product_id, + amount: amount + }); + + dialog_config.arProductID.push(product_id); + + }); + + fetch('<?php echo admin_url('admin-ajax.php'); ?>', { + method: 'POST', + body: new URLSearchParams({ + nonce: wpsg_revocation_nonce, + action: 'wpsg_mod_revocation', + do: 'ajaxDialogContent', + dialog_config: JSON.stringify(dialog_config), + }) + }).then(res => res.text()).then(html => { + + el_dialog_content.innerHTML = html; + el_dialog.classList.remove('loading'); + + }); + + }; + + // Button am Produkt + document.querySelectorAll('.wpsg_revocation_product_button').forEach(el => { + + el.addEventListener('click', event => { + + open_dialog(el); + + }); + + }); + + // Button Listener FlyOut + document.getElementById('wpsg_revocation_button').addEventListener('click', event => { open_dialog(); }); + + // GET Parameter verarbeiten + const urlParams = new URLSearchParams(window.location.search); + + const get_order_nr = urlParams.get('wpsg_revo_order'); + const get_product_nr = urlParams.get('wpsg_revo_product'); + const get_amount = urlParams.get('wpsg_revo_amount'); + const get_contact = urlParams.get('wpsg_revo_contact'); + + if (get_order_nr !== null) { + + document.addEventListener('DOMContentLoaded', () => { + + open_dialog(); + + const checkAndFillForm = () => { + + const form = el_dialog.querySelector('form#wpsg_revocation_form'); + + if (!form) { + + setTimeout(checkAndFillForm, 100); + return; + + } + + if (get_product_nr) { + + const productNrInput = form.querySelector('input[name*="[product_nr]"]'); + + if (productNrInput) productNrInput.value = get_product_nr; + + } + + if (get_order_nr) { + + const orderNrInput = form.querySelector('input[name*="[order_nr]"]'); + + if (orderNrInput) orderNrInput.value = get_order_nr; + + } + + if (get_amount) { + + const amountInput = form.querySelector('input[name*="[amount]"]'); + + if (amountInput) amountInput.value = get_amount; + + } + + if (get_contact) { + + const contactInput = form.querySelector('input[name="wpsg_revocation_reason[contact]"]'); + + if (contactInput) contactInput.value = get_contact; + + } + + }; + + checkAndFillForm(); + + }); + + } + + // Layer Listener + el_dialog.addEventListener('click', event => { + + if (!event.target.closest('.inner')) close_dialog(event); + + }); + + // Produkte in Bestellung auf der Seite Listener + document.querySelectorAll('.wpsg_revocation_order_product')?.forEach(el => { + + el.addEventListener('click', event => { + + if (!event.target.closest('input[type="checkbox"]')) { + + open_dialog(el); + + } + + }); + + }); + + // Close Button Listener + el_dialog.querySelectorAll('.close')?.forEach(el => { + + el.addEventListener('click', event => { close_dialog(event); }) + + }) + + // Submit Button Listener + el_dialog.querySelectorAll('.wpsg_revocation_button_submit')?.forEach(el => { + + el.addEventListener('click', event => { submit_dialog(event); }); + + }) + + // ESC Taste lauschen + document.addEventListener('keydown', function (e) { + + if (e.key === 'Escape') { + + el_dialog.classList.remove('visible'); + + } + + }); + +</script>
\ No newline at end of file diff --git a/views/mods/mod_revocation/wpsg_mod_kundenverwaltung_order_after_products.phtml b/views/mods/mod_revocation/wpsg_mod_kundenverwaltung_order_after_products.phtml new file mode 100644 index 0000000..841da99 --- /dev/null +++ b/views/mods/mod_revocation/wpsg_mod_kundenverwaltung_order_after_products.phtml @@ -0,0 +1,49 @@ +<?php + + declare(strict_types=1); + + /** + * @author: Daniel Schmitzer + * @date: 10.04.26 + * @time: 10:16 + */ + + namespace wpsgRevocation; + + use wpsg\M1; + + $view = \wpsg_ShopController::getShop()->view; + + /** @var \wpsg_order_product $oOrderProduct */ + $oOrderProduct = $view['oOrderProduct']; + + /** @var \wpsg_order $oOrder */ + $oOrder = $view['oOrder']; + + /** @var int $amount */ + $amount = $view['amount']; + +?> + +<tr> + <td colspan="2"> + + <?php if (Revocation::getRevocationPossible($oOrder->getId(), $oOrderProduct->getId())) { ?> + <div class="wpsg_revocation_order_product"> + <input type="checkbox" + class="wpsg_revocation_order_product_checkbox" + data-order_id="<?php echo $oOrder->getId(); ?>" + data-order_product_id="<?php echo $oOrderProduct->getId(); ?>" + data-product_id="<?php echo $oOrderProduct->getProduct()->getId(); ?>" + data-amount="<?php echo $amount; ?>" + /> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19,15V3H23V15H19M15,3A2,2 0 0,1 17,5V15C17,15.55 16.78,16.05 16.41,16.41L9.83,23L8.77,21.94C8.5,21.67 8.33,21.3 8.33,20.88L8.36,20.57L9.31,16H3C1.89,16 1,15.1 1,14V12C1,11.74 1.05,11.5 1.14,11.27L4.16,4.22C4.46,3.5 5.17,3 6,3H15M15,5H5.97L3,12V14H11.78L10.65,19.32L15,14.97V5Z" /></svg> + <span><?php echo __('Produkt widerrufen', 'wpsgRevocation'); ?></span> + </div> + <?php } else { ?> + + <p class="wpsg_revocation_complete"><?php echo __('Bereits komplett widerrufen', 'wpsgRevocation'); ?></p> + + <?php } ?> + </td> +</tr>
\ No newline at end of file diff --git a/views/mods/mod_revocation/wpsg_producttemplate_afterButton.phtml b/views/mods/mod_revocation/wpsg_producttemplate_afterButton.phtml new file mode 100644 index 0000000..241357e --- /dev/null +++ b/views/mods/mod_revocation/wpsg_producttemplate_afterButton.phtml @@ -0,0 +1,25 @@ +<?php + + declare(strict_types=1); + + /** + * @author: Daniel Schmitzer + * @date: 10.04.26 + * @time: 09:31 + */ + + namespace wpsgRevocation; + + use \wpsg\M1; + + // M1::d(\wpsg_ShopController::getShop()->view['data']); + +?> + +<?php if (\wpsg_ShopController::getShop()->get_option('wpsg_mod_revocation_view_product') === '1') { ?> + + <div class="wpsg_revocation_product_button" data-product_anr="<?php echo \wpsg_ShopController::getShop()->view['data']['anr']; ?>"> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19,15V3H23V15H19M15,3A2,2 0 0,1 17,5V15C17,15.55 16.78,16.05 16.41,16.41L9.83,23L8.77,21.94C8.5,21.67 8.33,21.3 8.33,20.88L8.36,20.57L9.31,16H3C1.89,16 1,15.1 1,14V12C1,11.74 1.05,11.5 1.14,11.27L4.16,4.22C4.46,3.5 5.17,3 6,3H15M15,5H5.97L3,12V14H11.78L10.65,19.32L15,14.97V5Z" /></svg> + </div> + +<?php } ?>
\ No newline at end of file diff --git a/views/mods/mod_revocation/wpsg_revocation.css b/views/mods/mod_revocation/wpsg_revocation.css new file mode 100644 index 0000000..9ee5d0f --- /dev/null +++ b/views/mods/mod_revocation/wpsg_revocation.css @@ -0,0 +1,58 @@ +#wpsg_revocation_button { position:fixed; right:0; top:25%; display:flex; gap:1rem; align-items:center; justify-content:flex-start; flex-wrap:nowrap; transform:translateX(calc(100% - (50px + 1rem + 0.5rem))); cursor:pointer; z-index:10; + background-color:white; border:1px solid black; border-radius:0.5rem; padding:0.5rem 1rem 0.5rem 0.5rem; transition:all 0.4s; + svg { width:50px; fill:black; } + span { white-space:nowrap; } + &:hover { transform:translateX(0.5rem); } +} + +#wpsg_revocation_dialog { + z-index:10; opacity:0; pointer-events:none; transition:all 0.4s; + position:fixed; left:0; top:0; height:100vh; width:100vw; + background-color:rgba(0,0,0,0.5); display:flex; align-items:center; justify-content:center; + &.visible { opacity:1; pointer-events:all; } + .inner { width:calc(100% - 3rem); height:auto; max-width:800px; max-height:800px; + border:1px solid black; position:relative; + background-color:white; border-radius:0.5rem; padding:1rem; display:flex; flex-direction:column; + & > .loading { transition:all 0.2s; opacity:0; pointer-events:none; background-color:rgba(0, 0, 0, 0.25); position:absolute; z-index:2; left:0; top:0; height:100%; width:100%; display:flex; align-items:center; justify-content:center; } + & > .header { height:50px; flex-shrink:0; flex-grow:0; + display:flex; align-items:center; justify-content:space-between; font-size:2rem; font-weight:bold; + .close { width:30px; height:30px; cursor:pointer; display:flex; align-items:center; justify-content:center; } + } + & > .content { flex-grow:0.2; overflow-y:auto; margin-top:1rem; margin-bottom:1rem; } + & > .footer { flex-shrink:0; flex-grow:0; display:flex; align-items:center; justify-content:start; height: 35px; margin-bottom: 2rem;} + #wpsg_error { padding-left:5px; color:red; } + } + &.loading > .inner > .loading { opacity:1; pointer-events:all; } +} + +.wpsg_revocation_product_button { + flex-shrink:0; padding:0.25rem; width:35px; height:35px; + border:1px solid black; display:flex; cursor:pointer; + svg { width:auto; } +} + +#wpsg_revocation_form { display:flex; flex-direction:column; gap:0.5rem; width:100%; + .wpsg_revocation_order_product > div { width:100%; } + .form_field { display:flex; width:100%; flex-direction:column; gap:0.125rem; + .label { color: black; font-size: 1.25rem; } + .value { display:flex; justify-content:stretch; gap:0.25rem; + input, textarea, select { width:auto; flex-grow:1; min-height:30px; text-indent:0.25rem; flex-shrink:1; } + textarea { min-height:90px; padding:0.25rem; } + select { height:36px; } + input[type="number"] { flex-shrink:2; flex-grow:0; } + } + } +} + +.wpsg_mod_kundenverwaltung_order { + .wpsg_revocation_order_product { display:inline-flex; align-items:center; gap:0.5rem; border:1px solid black; border-radius:0.5rem; padding:0.5rem; + margin-bottom:1rem; user-select:none; flex-direction: row; + & > svg { height:30px; width:30px; } + & > input { width:25px; height:25px; flex-shrink:0; } + & > .inner { cursor:pointer; } + } +} + +.wpsg_amount_label { + word-break: normal; +}
\ No newline at end of file diff --git a/views/mods/mod_revocation/wpsg_revocation.js b/views/mods/mod_revocation/wpsg_revocation.js new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/views/mods/mod_revocation/wpsg_revocation.js |
