Refactor code structure for improved readability and maintainability

This commit is contained in:
“VeLiTi”
2026-02-06 11:59:13 +01:00
parent fb5951d202
commit 9212492b75
48 changed files with 13072 additions and 11329 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
productold.php
test.php
find_undeclared_vars.php.php
GTM_DataLayer_Triggers.md

View File

@@ -4,7 +4,7 @@ defined('admin') or exit;
//------------------------------------------
// Languages supported
//------------------------------------------
$supportedLanguages = ['US', 'NL', 'DE', 'ES','FR', 'IT'];
$supportedLanguages = ['US', 'NL', 'DE', 'ES','FR'];
if(isset($_POST['generatefile'])){

View File

@@ -0,0 +1,70 @@
<?php
define('MorvalWatches', true);
// Start session
session_start();
// Includes
include './custom/settings/config.php';
include './custom/settings/settings.php';
include 'functions.php';
// Get the API token from session or authenticate
$token_refresh_buffer = 300;
if (!isset($_SESSION['api_token']) || !isset($_SESSION['api_token_expires']) || time() >= ($_SESSION['api_token_expires'] - $token_refresh_buffer)) {
$data = json_encode(array("clientID" => clientID, "clientsecret" => clientsecret), JSON_UNESCAPED_UNICODE);
$responses = ioAPIv2('/v2/authorization', $data,'');
if (!empty($responses)){$responses = json_decode($responses,true);}else{$responses = '400';}
if (isset($responses['token']) && isset($responses['token_valid'])) {
$_SESSION['api_token'] = $responses['token'];
$_SESSION['api_token_expires'] = strtotime($responses['token_valid']);
$clientsecret = $responses['token'];
} else {
$clientsecret = $responses['token'] ?? '';
}
} else {
$clientsecret = $_SESSION['api_token'];
}
// Set JSON header
header('Content-Type: application/json');
// Get order ID from request
$order_id = $_GET['order_id'] ?? null;
if (!$order_id) {
echo json_encode(['error' => 'No order ID provided']);
exit;
}
// Check transaction status
$transaction_data = ioAPIv2('/v2/transactions/txn_id='.$order_id,'',$clientsecret);
$transaction = json_decode($transaction_data, true);
if ($transaction && isset($transaction[0])) {
$payment_status_code = $transaction[0]['payment_status'] ?? 0;
// Map payment status codes: 1 = Paid, 101 = Pending, 102 = Failed, 103 = Expired, 999 = Cancelled
if ($payment_status_code == 1) {
$payment_status = 'success';
} elseif ($payment_status_code == 101) {
$payment_status = 'pending';
} elseif (in_array($payment_status_code, [102, 103, 999])) {
$payment_status = 'failed';
} else {
$payment_status = 'processing';
}
echo json_encode([
'status' => $payment_status,
'payment_status_code' => $payment_status_code
]);
} else {
echo json_encode([
'status' => 'processing',
'payment_status_code' => 101
]);
}
?>

1
cache/.htaccess vendored Normal file
View File

@@ -0,0 +1 @@
Deny from all

1376
cache/catalog.json vendored Normal file

File diff suppressed because it is too large Load Diff

496
cache/categories.json vendored Normal file
View File

@@ -0,0 +1,496 @@
[
{
"rowID": 17,
"name": "Watches",
"parent_id": 0,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:56:56",
"createdby": "MorvalWatches",
"updated": "2025-02-25 13:18:55",
"updatedby": "MorvalWatches",
"filter": 1,
"product_id": 57
},
{
"rowID": 18,
"name": "Thomas-I Date",
"parent_id": 17,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:57:20",
"createdby": "MorvalWatches",
"updated": "2025-05-27 13:34:46",
"updatedby": "paul@veliti.nl",
"filter": 1,
"product_id": 57
},
{
"rowID": 21,
"name": "fp_carrousel_1",
"parent_id": 0,
"status": 0,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:58:13",
"createdby": "MorvalWatches",
"updated": "2025-02-24 18:58:13",
"updatedby": null,
"filter": 0,
"product_id": 57
},
{
"rowID": 17,
"name": "Watches",
"parent_id": 0,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:56:56",
"createdby": "MorvalWatches",
"updated": "2025-02-25 13:18:55",
"updatedby": "MorvalWatches",
"filter": 1,
"product_id": 60
},
{
"rowID": 19,
"name": "Thomas-II Open Heart",
"parent_id": 17,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:57:37",
"createdby": "MorvalWatches",
"updated": "2025-05-27 13:34:39",
"updatedby": "paul@veliti.nl",
"filter": 1,
"product_id": 60
},
{
"rowID": 22,
"name": "fp_carrousel_2",
"parent_id": 0,
"status": 0,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:58:22",
"createdby": "MorvalWatches",
"updated": "2025-02-24 18:58:22",
"updatedby": null,
"filter": 0,
"product_id": 60
},
{
"rowID": 17,
"name": "Watches",
"parent_id": 0,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:56:56",
"createdby": "MorvalWatches",
"updated": "2025-02-25 13:18:55",
"updatedby": "MorvalWatches",
"filter": 1,
"product_id": 61
},
{
"rowID": 19,
"name": "Thomas-II Open Heart",
"parent_id": 17,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:57:37",
"createdby": "MorvalWatches",
"updated": "2025-05-27 13:34:39",
"updatedby": "paul@veliti.nl",
"filter": 1,
"product_id": 61
},
{
"rowID": 22,
"name": "fp_carrousel_2",
"parent_id": 0,
"status": 0,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:58:22",
"createdby": "MorvalWatches",
"updated": "2025-02-24 18:58:22",
"updatedby": null,
"filter": 0,
"product_id": 61
},
{
"rowID": 17,
"name": "Watches",
"parent_id": 0,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:56:56",
"createdby": "MorvalWatches",
"updated": "2025-02-25 13:18:55",
"updatedby": "MorvalWatches",
"filter": 1,
"product_id": 62
},
{
"rowID": 19,
"name": "Thomas-II Open Heart",
"parent_id": 17,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:57:37",
"createdby": "MorvalWatches",
"updated": "2025-05-27 13:34:39",
"updatedby": "paul@veliti.nl",
"filter": 1,
"product_id": 62
},
{
"rowID": 22,
"name": "fp_carrousel_2",
"parent_id": 0,
"status": 0,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:58:22",
"createdby": "MorvalWatches",
"updated": "2025-02-24 18:58:22",
"updatedby": null,
"filter": 0,
"product_id": 62
},
{
"rowID": 17,
"name": "Watches",
"parent_id": 0,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:56:56",
"createdby": "MorvalWatches",
"updated": "2025-02-25 13:18:55",
"updatedby": "MorvalWatches",
"filter": 1,
"product_id": 63
},
{
"rowID": 19,
"name": "Thomas-II Open Heart",
"parent_id": 17,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:57:37",
"createdby": "MorvalWatches",
"updated": "2025-05-27 13:34:39",
"updatedby": "paul@veliti.nl",
"filter": 1,
"product_id": 63
},
{
"rowID": 22,
"name": "fp_carrousel_2",
"parent_id": 0,
"status": 0,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:58:22",
"createdby": "MorvalWatches",
"updated": "2025-02-24 18:58:22",
"updatedby": null,
"filter": 0,
"product_id": 63
},
{
"rowID": 17,
"name": "Watches",
"parent_id": 0,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:56:56",
"createdby": "MorvalWatches",
"updated": "2025-02-25 13:18:55",
"updatedby": "MorvalWatches",
"filter": 1,
"product_id": 64
},
{
"rowID": 19,
"name": "Thomas-II Open Heart",
"parent_id": 17,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:57:37",
"createdby": "MorvalWatches",
"updated": "2025-05-27 13:34:39",
"updatedby": "paul@veliti.nl",
"filter": 1,
"product_id": 64
},
{
"rowID": 22,
"name": "fp_carrousel_2",
"parent_id": 0,
"status": 0,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:58:22",
"createdby": "MorvalWatches",
"updated": "2025-02-24 18:58:22",
"updatedby": null,
"filter": 0,
"product_id": 64
},
{
"rowID": 20,
"name": "Accessories",
"parent_id": 0,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:57:55",
"createdby": "MorvalWatches",
"updated": "2025-02-25 13:19:24",
"updatedby": "MorvalWatches",
"filter": 1,
"product_id": 65
},
{
"rowID": 23,
"name": "Bracelets",
"parent_id": 20,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-25 13:20:01",
"createdby": "MorvalWatches",
"updated": "2025-02-25 13:20:01",
"updatedby": null,
"filter": 1,
"product_id": 65
},
{
"rowID": 20,
"name": "Accessories",
"parent_id": 0,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:57:55",
"createdby": "MorvalWatches",
"updated": "2025-02-25 13:19:24",
"updatedby": "MorvalWatches",
"filter": 1,
"product_id": 66
},
{
"rowID": 23,
"name": "Bracelets",
"parent_id": 20,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-25 13:20:01",
"createdby": "MorvalWatches",
"updated": "2025-02-25 13:20:01",
"updatedby": null,
"filter": 1,
"product_id": 66
},
{
"rowID": 20,
"name": "Accessories",
"parent_id": 0,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:57:55",
"createdby": "MorvalWatches",
"updated": "2025-02-25 13:19:24",
"updatedby": "MorvalWatches",
"filter": 1,
"product_id": 67
},
{
"rowID": 23,
"name": "Bracelets",
"parent_id": 20,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-25 13:20:01",
"createdby": "MorvalWatches",
"updated": "2025-02-25 13:20:01",
"updatedby": null,
"filter": 1,
"product_id": 67
},
{
"rowID": 20,
"name": "Accessories",
"parent_id": 0,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:57:55",
"createdby": "MorvalWatches",
"updated": "2025-02-25 13:19:24",
"updatedby": "MorvalWatches",
"filter": 1,
"product_id": 68
},
{
"rowID": 23,
"name": "Bracelets",
"parent_id": 20,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-25 13:20:01",
"createdby": "MorvalWatches",
"updated": "2025-02-25 13:20:01",
"updatedby": null,
"filter": 1,
"product_id": 68
},
{
"rowID": 17,
"name": "Watches",
"parent_id": 0,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:56:56",
"createdby": "MorvalWatches",
"updated": "2025-02-25 13:18:55",
"updatedby": "MorvalWatches",
"filter": 1,
"product_id": 69
},
{
"rowID": 18,
"name": "Thomas-I Date",
"parent_id": 17,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:57:20",
"createdby": "MorvalWatches",
"updated": "2025-05-27 13:34:46",
"updatedby": "paul@veliti.nl",
"filter": 1,
"product_id": 69
},
{
"rowID": 21,
"name": "fp_carrousel_1",
"parent_id": 0,
"status": 0,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:58:13",
"createdby": "MorvalWatches",
"updated": "2025-02-24 18:58:13",
"updatedby": null,
"filter": 0,
"product_id": 69
},
{
"rowID": 17,
"name": "Watches",
"parent_id": 0,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:56:56",
"createdby": "MorvalWatches",
"updated": "2025-02-25 13:18:55",
"updatedby": "MorvalWatches",
"filter": 1,
"product_id": 70
},
{
"rowID": 18,
"name": "Thomas-I Date",
"parent_id": 17,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:57:20",
"createdby": "MorvalWatches",
"updated": "2025-05-27 13:34:46",
"updatedby": "paul@veliti.nl",
"filter": 1,
"product_id": 70
},
{
"rowID": 21,
"name": "fp_carrousel_1",
"parent_id": 0,
"status": 0,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:58:13",
"createdby": "MorvalWatches",
"updated": "2025-02-24 18:58:13",
"updatedby": null,
"filter": 0,
"product_id": 70
},
{
"rowID": 17,
"name": "Watches",
"parent_id": 0,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:56:56",
"createdby": "MorvalWatches",
"updated": "2025-02-25 13:18:55",
"updatedby": "MorvalWatches",
"filter": 1,
"product_id": 71
},
{
"rowID": 18,
"name": "Thomas-I Date",
"parent_id": 17,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:57:20",
"createdby": "MorvalWatches",
"updated": "2025-05-27 13:34:46",
"updatedby": "paul@veliti.nl",
"filter": 1,
"product_id": 71
},
{
"rowID": 21,
"name": "fp_carrousel_1",
"parent_id": 0,
"status": 0,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:58:13",
"createdby": "MorvalWatches",
"updated": "2025-02-24 18:58:13",
"updatedby": null,
"filter": 0,
"product_id": 71
},
{
"rowID": 17,
"name": "Watches",
"parent_id": 0,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:56:56",
"createdby": "MorvalWatches",
"updated": "2025-02-25 13:18:55",
"updatedby": "MorvalWatches",
"filter": 1,
"product_id": 72
},
{
"rowID": 18,
"name": "Thomas-I Date",
"parent_id": 17,
"status": 1,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:57:20",
"createdby": "MorvalWatches",
"updated": "2025-05-27 13:34:46",
"updatedby": "paul@veliti.nl",
"filter": 1,
"product_id": 72
},
{
"rowID": 21,
"name": "fp_carrousel_1",
"parent_id": 0,
"status": 0,
"accounthierarchy": "{\"salesid\":\"148-MorvalWatches\",\"soldto\":\"\"}",
"created": "2025-02-24 18:58:13",
"createdby": "MorvalWatches",
"updated": "2025-02-24 18:58:13",
"updatedby": null,
"filter": 0,
"product_id": 72
}
]

View File

@@ -207,7 +207,7 @@ $view .= '
<div class="buttons">
<input type="submit" form ="cart-form" value="'.$btn_emptycart.'" name="emptycart" class="btn" title="Remove cart" style="font-size:10px;background:none;">
<input type="submit" form ="cart-form" value="'.$btn_update.'" name="update" class="btn" title="Refresh cart">
<input type="submit" form ="cart-form" value="'.$btn_checkout.'" name="checkout" class="btn" style="background-color:green;">
<input type="submit" form ="cart-form" value="'.$btn_checkout.'" name="checkout" class="btn btn-checkout-sticky" style="background-color:green;">
</div>
</div>
';

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -0,0 +1,21 @@
{
"name": "MyWebSite",
"short_name": "MySite",
"icons": [
{
"src": "/web-app-manifest-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "/web-app-manifest-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

71
custom/assets/wero.svg Normal file
View File

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Layer_1" data-name="Layer 1" viewBox="0 0 480 182">
<defs>
<style>
.cls-1 {
fill: url(#linear-gradient);
}
.cls-1, .cls-2, .cls-3, .cls-4, .cls-5, .cls-6, .cls-7, .cls-8, .cls-9 {
stroke-width: 0px;
}
.cls-2, .cls-3 {
fill-rule: evenodd;
}
.cls-2, .cls-6 {
fill: #232323;
}
.cls-3, .cls-8 {
fill: #fff;
}
.cls-4 {
fill: url(#linear-gradient-2);
}
.cls-5 {
fill: #1d1c1c;
}
.cls-7 {
fill: #c06;
}
.cls-9 {
fill: #fff48d;
}
</style>
<linearGradient id="linear-gradient" x1="352.72" y1="95.3" x2="330.2" y2="67.73" gradientTransform="translate(0 184) scale(1 -1)" gradientUnits="userSpaceOnUse">
<stop offset=".02" stop-color="#1d1c1c" stop-opacity="0"></stop>
<stop offset=".68" stop-color="#1d1c1c"></stop>
</linearGradient>
<linearGradient id="linear-gradient-2" x1="313.44" y1="89.45" x2="336.52" y2="112.26" gradientTransform="translate(0 184) scale(1 -1)" gradientUnits="userSpaceOnUse">
<stop offset=".02" stop-color="#1d1c1c" stop-opacity="0"></stop>
<stop offset=".68" stop-color="#1d1c1c"></stop>
</linearGradient>
</defs>
<rect class="cls-9" x="0" width="480" height="182" rx="13" ry="13"></rect>
<g>
<path class="cls-8" d="M11.02,22.87v136.4c0,6.53,5.37,11.87,11.93,11.87h81.89c61.91,0,88.74-34.49,88.74-80.25S166.74,11,104.83,11H22.94c-6.56,0-11.93,5.34-11.93,11.87Z"></path>
<path class="cls-7" d="M65.83,44.48v100.79h44.07c40.02,0,57.37-22.5,57.37-54.31s-17.36-54.07-57.37-54.07h-36.44c-4.23,0-7.63,3.44-7.63,7.6Z"></path>
<path class="cls-2" d="M33.62,160.28h71.21c50.04,0,77.65-24.63,77.65-69.33,0-25.76-10.08-69.03-77.65-69.03H33.62c-6.32,0-11.45,5.1-11.45,11.4v115.57c0,6.29,5.13,11.4,11.45,11.4ZM25.98,33.32c0-4.21,3.4-7.6,7.63-7.6h71.21c27.55,0,73.83,8.49,73.83,65.23,0,42.26-26.24,65.53-73.83,65.53H33.62c-4.23,0-7.63-3.38-7.63-7.6V33.32Z"></path>
<path class="cls-3" d="M87.51,76.3c-1.34-.48-2.74-.72-4.26-.72v-.06h-10.09v24.34h10.21c1.81,0,3.38-.36,4.73-.96,1.34-.66,2.45-1.5,3.33-2.58.88-1.08,1.52-2.4,1.98-3.9.41-1.5.64-3.12.64-4.92,0-2.04-.29-3.78-.82-5.28-.58-1.44-1.34-2.7-2.27-3.72-.99-.96-2.1-1.74-3.44-2.22ZM85.12,95.07c-.76.24-1.46.36-2.22.36v.06h-4.61v-15.35h3.73c1.28,0,2.33.18,3.21.54.88.36,1.58.96,2.1,1.62.52.66.93,1.56,1.17,2.52.23.96.35,2.1.35,3.3,0,1.38-.18,2.46-.52,3.42-.35.96-.82,1.68-1.34,2.28-.52.6-1.17,1.02-1.87,1.26Z"></path>
<path class="cls-8" d="M115.11,75.59v4.5h-12.49v5.22h11.49v4.14h-11.49v5.94h12.78v4.5h-17.97v-24.34h17.68v.06Z"></path>
<path class="cls-3" d="M141.83,99.93l-8.87-24.34h-5.42l-8.93,24.34h5.25l1.87-5.4h8.87l1.81,5.4h5.43ZM130.27,81.58l2.98,8.93h-6.12l3.09-8.93h.06Z"></path>
<path class="cls-8" d="M150.29,75.58v19.85h11.55v4.5h-16.74v-24.34h5.19Z"></path>
<path class="cls-6" d="M45.35,100.29c6.32,0,11.44-5.12,11.44-11.45s-5.12-11.45-11.44-11.45-11.44,5.12-11.44,11.45,5.12,11.45,11.44,11.45Z"></path>
<path class="cls-6" d="M52.16,146.08c-8.86,0-15.96-7.65-15.96-17.05v-13.31c0-4.7,3.55-8.56,8.01-8.56s8.01,3.8,8.01,8.56v30.36h-.06Z"></path>
</g>
<g>
<path class="cls-5" d="M405.6,91.62c0-13.38,9.52-25.57,25.96-25.57s26.03,12.2,26.03,25.57-9.52,25.57-26.03,25.57c-16.44,0-25.96-12.2-25.96-25.57ZM443.14,91.62c0-6.45-4.25-12.4-11.58-12.4s-11.58,5.96-11.58,12.4,4.32,12.41,11.58,12.41,11.58-5.96,11.58-12.41Z"></path>
<path class="cls-5" d="M395.49,101.12c5.48-3.12,8.77-9.08,8.77-15.66,0-9.77-7.06-18.09-18.02-18.09h-23.01v48.51h14.25v-12.4h2.67l8.15,12.4h16.78l-9.59-14.76ZM383.37,92.31h-5.89v-13.72h5.96c3.84,0,6.3,3.12,6.3,6.86s-2.54,6.86-6.37,6.86Z"></path>
<path class="cls-5" d="M298.18,67.31l-8.55,28.91-8.34-28.91h-11.35l-8.41,28.91-8.48-28.91h-15.04l17.23,48.42h12.37l8-26.36,7.93,26.36h12.44l17.23-48.42h-15.04Z"></path>
<path class="cls-5" d="M334.78,103.91h-.03c-5.33,0-9.07-3.22-10.67-7.48h36.21c.29-1.6.44-3.24.44-4.9,0-13.34-9.49-25.51-25.95-25.52v13.14c5.36.01,9.06,3.23,10.65,7.48h-36.16c-.29,1.6-.44,3.24-.44,4.9,0,13.35,9.5,25.53,25.91,25.53h.03v-13.15Z"></path>
<path class="cls-1" d="M334.75,117.05c.56,0,1.11-.02,1.65-.04,3.33-.17,6.36-.85,9.06-1.94,2.7-1.09,5.07-2.6,7.08-4.42,2.02-1.82,3.68-3.95,4.97-6.3,1.17-2.14,2.03-4.45,2.57-6.86h-15.09c-.31.64-.67,1.26-1.08,1.83-.56.79-1.22,1.5-1.97,2.11-.75.62-1.59,1.14-2.51,1.54-.92.4-1.93.68-3.02.83-.53.07-1.08.11-1.65.11-3.39,0-6.14-1.31-8.11-3.36l-9.81,9.92c4.36,4.03,10.41,6.57,17.91,6.57Z"></path>
<path class="cls-4" d="M334.75,66c-13.92,0-22.87,8.76-25.26,19.56h15.04c1.8-3.72,5.34-6.42,10.22-6.42,3.89,0,6.91,1.68,8.88,4.22l9.9-10.01c-4.42-4.48-10.78-7.35-18.77-7.35Z"></path>
</g>
<path class="cls-5" d="M215.61,145c-1.1,0-2-.9-2-2V39c0-1.1.9-2,2-2s2,.9,2,2v104c0,1.1-.9,2-2,2Z"></path>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -39,14 +39,14 @@ function template_header($title,$head) {
if (maintenanceMode){$maintenanceMode = maintenanceMode();} else {$maintenanceMode = '';}
$veliti_analytics = '';
if (veliti_analytics && $_COOKIE['cookie_consent'] == 'accepted'){
$veliti_analytics = '<script src="'.$base_url.'/lib/analytics/analytics.js"></script>';
if (veliti_analytics && (!isset($_COOKIE['cookie_consent']) || (isset($_COOKIE['cookie_consent']) && $_COOKIE['cookie_consent'] != 'declined'))){
$veliti_analytics = '<script src="'.base_url.'lib/analytics/analytics.js"></script>';
}
$tag_manager_header = '';
$tag_manager_body = '';
if (isset($_COOKIE['cookie_consent']) && $_COOKIE['cookie_consent'] == 'accepted') {
if (!isset($_COOKIE['cookie_consent']) || (isset($_COOKIE['cookie_consent']) && $_COOKIE['cookie_consent'] != 'declined')) {
$tag_manager_header = "
<script>
@@ -70,6 +70,11 @@ $view = '
<link rel="icon" type="image/png" href="'.base_url.icon_image.'">
<link href="'.base_url.'custom/css/main.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v6.0.0/css/all.css">
<link rel="icon" type="image/png" href="'.base_url.'custom/assets/favicon/favicon-96x96.png" sizes="96x96" />
<link rel="shortcut icon" href="'.base_url.'custom/assets/favicon/favicon.ico" />
<link rel="apple-touch-icon" sizes="180x180" href="'.base_url.'custom/assets/favicon/apple-touch-icon.png" />
<meta name="apple-mobile-web-app-title" content="MorvalWatches" />
<link rel="manifest" href="'.base_url.'custom/assets/favicon/site.webmanifest" />
'.$head.'
'.$tag_manager_header.'
<script>
@@ -197,6 +202,9 @@ $view = '
<span class="star-rating">★★★★★</span>
'.($header_rating ?? 'Client rate 5.0/5.0').'
</div>
<div>
<a href="https://www.valuedshops.com/webshop/Morval-Watches_1223642" class="webwinkelkeurPopup" title="WebwinkelKeur" target="_blank"><img src="https://dashboard.webwinkelkeur.nl/banners/5/1223642/1767769194000.svg" width="18" height="18" alt="WebwinkelKeur Banner"></a>
</div>
</div>
<!-- Header -->
@@ -599,10 +607,11 @@ function template_footer() {
<div class="container">
<div class="payment-methods">
<img src="'.base_url.'custom/assets/iDEAL.png" alt="iDeal" class="payment-method">
<img src="'.base_url.'custom/assets/wero.svg" alt="iDeal" class="payment-method">
<img src="'.base_url.'custom/assets/mastercard.png" alt="Mastercard" class="payment-method">
<img src="'.base_url.'custom/assets/visa.png" alt="Visa" class="payment-method">
<img src="'.base_url.'custom/assets/paypal.png" alt="Pay Pal" class="payment-method">
<a href="https://www.valuedshops.com/webshop/Morval-Watches_1223642" class="webwinkelkeurPopup" title="WebwinkelKeur" target="_blank"><img src="https://dashboard.webwinkelkeur.nl/banners/5/1223642/1767769194000.svg" width="32" height="32" alt="WebwinkelKeur Banner"></a>
</div>
<div class="footer-bottom">
@@ -879,7 +888,7 @@ EOT;
// Cookie consent banner
function cookie_consent() {
if (isset($_COOKIE['cookie_consent']) && $_COOKIE['cookie_consent'] == 'accepted') {
if (isset($_COOKIE['cookie_consent'])) {
return '';
}
@@ -897,8 +906,8 @@ function cookie_consent() {
location.reload();
};
document.getElementById("decline-cookies").onclick = function() {
document.cookie = "cookie_consent=declined; path=/; max-age=15768000";
document.getElementById("cookie-consent-banner").style.display = "none";
document.cookie = "cookie_consent=declined; path=/; max-age=432000";
location.reload();
};
</script>
';

View File

@@ -112,6 +112,77 @@ defined(security_key) or exit;
color: var(--color-dark-blue);
}
/* Return Request Section Styling */
.return-request-section {
background-color: var(--color-lighter-gray);
border: 2px solid var(--color-primary);
border-radius: 8px;
padding: 30px;
margin: 40px 0;
}
.copy-btn-container {
display: flex;
align-items: center;
gap: 10px;
}
.copy-btn {
background-color: var(--color-primary);
color: var(--color-white);
padding: 10px 24px;
border: none;
border-radius: 4px;
font-weight: 600;
font-size: 14px;
cursor: pointer;
transition: background-color 0.3s ease, transform 0.2s ease;
box-shadow: 0 2px 4px rgba(255, 111, 0, 0.25);
}
.copy-btn:hover {
background-color: var(--color-primary-dark);
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(255, 111, 0, 0.35);
}
.copy-btn:active {
transform: translateY(0);
background-color: var(--color-primary-darker);
}
.copy-success {
color: var(--color-green);
font-size: 14px;
font-weight: 600;
opacity: 0;
transition: opacity 0.3s ease;
}
.copy-success.show {
opacity: 1;
}
.template-textarea {
width: 100%;
min-height: 350px;
padding: 15px;
border: 2px solid var(--color-gray);
border-radius: 4px;
font-family: 'Courier New', monospace;
font-size: 14px;
line-height: 1.6;
resize: vertical;
background-color: var(--color-white);
color: var(--color-text-dark);
box-sizing: border-box;
}
.template-textarea:focus {
outline: none;
border-color: var(--color-primary);
}
@media (max-width: 768px) {
.content-section {
padding: 40px 0;
@@ -157,6 +228,31 @@ defined(security_key) or exit;
.content-section h2 + ul {
margin-left: 25px;
}
.return-request-section {
padding: 20px;
margin: 30px 0;
}
.template-header {
flex-direction: column;
align-items: flex-start;
gap: 15px;
}
.copy-btn-container {
width: 100%;
justify-content: space-between;
}
.copy-btn {
flex: 1;
}
.template-textarea {
min-height: 300px;
font-size: 13px;
}
}
@media (max-width: 576px) {
@@ -207,6 +303,22 @@ defined(security_key) or exit;
.content-section h2 + ul {
margin-left: 15px;
}
.return-request-section {
padding: 15px;
margin: 20px 0;
}
.copy-btn {
padding: 10px 20px;
font-size: 13px;
}
.template-textarea {
min-height: 280px;
font-size: 12px;
padding: 12px;
}
}
</style>
@@ -223,7 +335,86 @@ defined(security_key) or exit;
<h2>Register a Return</h2>
<p>To exercise this right, you can contact us via <a href="mailto:info@morvalwatches.com">info@morvalwatches.com</a>. We will then refund the order amount within 14 days after registering your return, provided the product has been received back in good condition.</p>
<h2>Making a Return</h2>
<p>Use the template below to register your return. Click the "Copy Template" button, insert in your email client, fill in your details and send it to <a href="mailto:info@morvalwatches.com">info@morvalwatches.com</a>.</p>
<!-- Return Request Section with Template Always Visible -->
<div class="return-request-section">
<textarea class="template-textarea" id="templateText" readonly>I would like to register a return for my recent order.
ORDER DETAILS:
Order Number: [Please enter your order number]
Order Date: [Please enter the date you placed your order]
Product(s): [Please list the product(s) you wish to return]
REASON FOR RETURN:
[Please explain your reason for returning the product(s)]
CUSTOMER INFORMATION:
Name: [Your full name]
Email: [Your email address]
Phone: [Your phone number]
Return Address: [Your full address where the product should be collected or returned to]
I confirm that I am returning the product(s) within 14 days of receipt, with all supplied accessories, in their original condition and packaging.
Please confirm receipt of this return request and provide instructions for the return shipping.
Best regards,
[Your name]</textarea>
</div>
<div class="template-header">
<div class="copy-btn-container">
<button class="copy-btn" id="copyBtn">Copy Template</button>
<span class="copy-success" id="copySuccess">✓ Copied!</span>
</div>
</div>
<h2>Returnadres</h2>
<p>
<?php echo company_name; ?> <br>
<?php echo company_adres; ?><br>
<?php echo company_postal . ' ' . footer_city; ?><br>
<?php echo footer_country; ?>
</p>
</div>
</div>
<script>
// Get elements
const copyBtn = document.getElementById('copyBtn');
const templateText = document.getElementById('templateText');
const copySuccess = document.getElementById('copySuccess');
// Copy template to clipboard
copyBtn.addEventListener('click', function() {
templateText.select();
templateText.setSelectionRange(0, 99999); // For mobile devices
try {
document.execCommand('copy');
// Show success message
copySuccess.classList.add('show');
// Change button text temporarily
const originalText = copyBtn.textContent;
copyBtn.textContent = 'Copied!';
// Reset after 2 seconds
setTimeout(function() {
copySuccess.classList.remove('show');
copyBtn.textContent = originalText;
}, 2000);
} catch (err) {
console.error('Failed to copy text: ', err);
alert('Failed to copy template. Please select and copy manually.');
}
// Deselect text
window.getSelection().removeAllRanges();
});
</script>
<?=template_footer()?>

View File

@@ -232,4 +232,43 @@ $cookie_text = 'Cookies';
$contact_text = 'Kontakt';
$returns_text = 'Rückgaberecht';
$complaint_text = 'Beschwerden';
// Payment Status Messages
$payment_success_title = "Zahlung erfolgreich!";
$payment_success_message = "Ihre Bestellung wurde bestätigt und eine E-Mail-Bestätigung wurde an Ihre E-Mail-Adresse gesendet.";
$payment_pending_title = "Zahlung ausstehend";
$payment_pending_message = "Ihre Bestellung ist eingegangen und wartet auf Zahlungsbestätigung. Sie erhalten eine E-Mail, sobald die Zahlung bestätigt wurde.";
$payment_processing_title = "Zahlung wird verarbeitet...";
$payment_processing_message = "Bitte warten Sie, während wir Ihre Zahlung bestätigen. Dies kann einige Momente dauern.";
$payment_failed_title = "Zahlung nicht erfolgreich";
$payment_failed_message = "Leider konnte Ihre Zahlung nicht verarbeitet werden. Bitte versuchen Sie es erneut oder wählen Sie eine andere Zahlungsmethode.";
// Button Labels
$order_number_label = "Bestellnummer";
$continue_shopping_btn = "Weiter einkaufen";
$return_to_checkout_btn = "Zurück zur Kasse";
$view_cart_btn = "Warenkorb ansehen";
// Checkout Step Labels
$step_contact = "Kontakt";
$step_payment = "Zahlung";
$step_shipping = "Versand";
$step_review = "Überprüfung";
// Checkout Button Text
$continue_text = "Weiter";
$back_text = "Zurück";
$edit_text = "Bearbeiten";
// Checkout Additional Labels
$contact_information = "Kontaktinformationen";
$customer_email = "E-Mail";
$account_optional = "(Optional)";
$select_payment = "Bitte wählen Sie eine Zahlungsmethode";
$ship_to = "Versand nach";
$bank_transfer = "Banküberweisung";
$card_payment = "Kredit-/Debitkarte";
?>

View File

@@ -232,4 +232,43 @@ $cookie_text = 'Cookies';
$contact_text = 'Contacto';
$returns_text = 'Política de Devoluciones';
$complaint_text = 'Quejas';
// Payment Status Messages
$payment_success_title = "¡Pago exitoso!";
$payment_success_message = "Su pedido ha sido confirmado y se ha enviado un correo electrónico de confirmación a su dirección de correo electrónico.";
$payment_pending_title = "Pago pendiente";
$payment_pending_message = "Su pedido ha sido recibido y está esperando la confirmación del pago. Recibirá un correo electrónico una vez que se confirme el pago.";
$payment_processing_title = "Procesando pago...";
$payment_processing_message = "Por favor espere mientras confirmamos su pago. Esto puede tardar unos momentos.";
$payment_failed_title = "Pago no exitoso";
$payment_failed_message = "Desafortunadamente, su pago no pudo ser procesado. Por favor intente nuevamente o elija un método de pago diferente.";
// Button Labels
$order_number_label = "Número de pedido";
$continue_shopping_btn = "Continuar comprando";
$return_to_checkout_btn = "Volver al pago";
$view_cart_btn = "Ver carrito";
// Checkout Step Labels
$step_contact = "Contacto";
$step_payment = "Pago";
$step_shipping = "Envío";
$step_review = "Revisar";
// Checkout Button Text
$continue_text = "Continuar";
$back_text = "Atrás";
$edit_text = "Editar";
// Checkout Additional Labels
$contact_information = "Información de Contacto";
$customer_email = "Correo electrónico";
$account_optional = "(Opcional)";
$select_payment = "Por favor seleccione un método de pago";
$ship_to = "Enviar a";
$bank_transfer = "Transferencia Bancaria";
$card_payment = "Tarjeta de Crédito / Débito";
?>

View File

@@ -231,4 +231,43 @@ $cookie_text = 'Cookies';
$contact_text = 'Contact';
$returns_text = 'Politique de Retour';
$complaint_text = 'Réclamations';
// Payment Status Messages
$payment_success_title = "Paiement réussi !";
$payment_success_message = "Votre commande a été confirmée et un e-mail de confirmation a été envoyé à votre adresse e-mail.";
$payment_pending_title = "Paiement en attente";
$payment_pending_message = "Votre commande a été reçue et attend la confirmation du paiement. Vous recevrez un e-mail une fois le paiement confirmé.";
$payment_processing_title = "Traitement du paiement...";
$payment_processing_message = "Veuillez patienter pendant que nous confirmons votre paiement. Cela peut prendre quelques instants.";
$payment_failed_title = "Paiement non réussi";
$payment_failed_message = "Malheureusement, votre paiement n'a pas pu être traité. Veuillez réessayer ou choisir un autre moyen de paiement.";
// Button Labels
$order_number_label = "Numéro de commande";
$continue_shopping_btn = "Continuer les achats";
$return_to_checkout_btn = "Retour au paiement";
$view_cart_btn = "Voir le panier";
// Checkout Step Labels
$step_contact = "Contact";
$step_payment = "Paiement";
$step_shipping = "Livraison";
$step_review = "Révision";
// Checkout Button Text
$continue_text = "Continuer";
$back_text = "Retour";
$edit_text = "Modifier";
// Checkout Additional Labels
$contact_information = "Informations de Contact";
$customer_email = "Email";
$account_optional = "(Facultatif)";
$select_payment = "Veuillez sélectionner un mode de paiement";
$ship_to = "Expédier à";
$bank_transfer = "Virement Bancaire";
$card_payment = "Carte de Crédit / Débit";
?>

View File

@@ -19,4 +19,43 @@ $order_consent_3 = 'Termini e condizioni';
$order_consent_4 = 'e la';
$order_consent_5 = 'Informativa sulla privacy';
$btn_place_order = 'Acquista';
// Payment Status Messages
$payment_success_title = "Pagamento riuscito!";
$payment_success_message = "Il tuo ordine è stato confermato ed è stata inviata un'email di conferma al tuo indirizzo email.";
$payment_pending_title = "Pagamento in sospeso";
$payment_pending_message = "Il tuo ordine è stato ricevuto ed è in attesa di conferma del pagamento. Riceverai un'email una volta confermato il pagamento.";
$payment_processing_title = "Elaborazione pagamento...";
$payment_processing_message = "Attendi mentre confermiamo il tuo pagamento. Potrebbero essere necessari alcuni istanti.";
$payment_failed_title = "Pagamento non riuscito";
$payment_failed_message = "Purtroppo il tuo pagamento non è stato elaborato. Riprova o scegli un metodo di pagamento diverso.";
// Button Labels
$order_number_label = "Numero d'ordine";
$continue_shopping_btn = "Continua gli acquisti";
$return_to_checkout_btn = "Torna al checkout";
$view_cart_btn = "Visualizza carrello";
// Checkout Step Labels
$step_contact = "Contatto";
$step_payment = "Pagamento";
$step_shipping = "Spedizione";
$step_review = "Revisione";
// Checkout Button Text
$continue_text = "Continua";
$back_text = "Indietro";
$edit_text = "Modifica";
// Checkout Additional Labels
$contact_information = "Informazioni di Contatto";
$customer_email = "Email";
$account_optional = "(Facoltativo)";
$select_payment = "Seleziona un metodo di pagamento";
$ship_to = "Spedire a";
$bank_transfer = "Bonifico Bancario";
$card_payment = "Carta di Credito / Debito";
?>

View File

@@ -242,4 +242,43 @@ $cookie_text = 'Cookies';
$contact_text = 'Contact';
$returns_text = 'Retourbeleid';
$complaint_text = 'Klachten';
// Payment Status Messages
$payment_success_title = "Betaling geslaagd!";
$payment_success_message = "Uw bestelling is bevestigd en een bevestigingsmail is verzonden naar uw e-mailadres.";
$payment_pending_title = "Betaling in behandeling";
$payment_pending_message = "Uw bestelling is ontvangen en wacht op betalingsbevestiging. U ontvangt een e-mail zodra de betaling is bevestigd.";
$payment_processing_title = "Betaling verwerken...";
$payment_processing_message = "Een moment geduld terwijl we uw betaling bevestigen. Dit kan enkele ogenblikken duren.";
$payment_failed_title = "Betaling niet geslaagd";
$payment_failed_message = "Helaas kon uw betaling niet worden verwerkt. Probeer het opnieuw of kies een andere betaalmethode.";
// Button Labels
$order_number_label = "Bestelnummer";
$continue_shopping_btn = "Verder winkelen";
$return_to_checkout_btn = "Terug naar afrekenen";
$view_cart_btn = "Bekijk winkelwagen";
// Checkout Step Labels
$step_contact = "Contact";
$step_payment = "Betaling";
$step_shipping = "Verzending";
$step_review = "Beoordeling";
// Checkout Button Text
$continue_text = "Doorgaan";
$back_text = "Terug";
$edit_text = "Bewerken";
// Checkout Additional Labels
$contact_information = "Contactinformatie";
$customer_email = "E-mail";
$account_optional = "(Optioneel)";
$select_payment = "Selecteer een betaalmethode";
$ship_to = "Verzenden naar";
$bank_transfer = "Bankoverschrijving";
$card_payment = "Credit- / Debetkaart";
?>

View File

@@ -243,4 +243,43 @@ $cookie_text = 'Cookies';
$contact_text = 'Contact';
$returns_text = 'Return Policy';
$complaint_text = 'Complaints';
// Payment Status Messages
$payment_success_title = "Payment Successful!";
$payment_success_message = "Your order has been confirmed and an email confirmation has been sent to your email address.";
$payment_pending_title = "Payment Pending";
$payment_pending_message = "Your order has been received and is awaiting payment confirmation. You will receive an email once the payment is confirmed.";
$payment_processing_title = "Processing Payment...";
$payment_processing_message = "Please wait while we confirm your payment. This may take a few moments.";
$payment_failed_title = "Payment Not Successful";
$payment_failed_message = "Unfortunately, your payment could not be processed. Please try again or choose a different payment method.";
// Button Labels
$order_number_label = "Order number";
$continue_shopping_btn = "Continue Shopping";
$return_to_checkout_btn = "Return to Checkout";
$view_cart_btn = "View Cart";
// Checkout Step Labels
$step_contact = "Contact";
$step_payment = "Payment";
$step_shipping = "Shipping";
$step_review = "Review";
// Checkout Button Text
$continue_text = "Continue";
$back_text = "Back";
$edit_text = "Edit";
// Checkout Additional Labels
$contact_information = "Contact Information";
$customer_email = "Email";
$account_optional = "(Optional)";
$select_payment = "Please select a payment method";
$ship_to = "Ship to";
$bank_transfer = "Bank Transfer";
$card_payment = "Credit / Debit Card";
?>

View File

@@ -42,38 +42,51 @@ require dirname(__FILE__).'/lib/mail/Exception.php';
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
function send_mail_by_PHPMailer($to, $subject, $message, $attachment, $attachment_name){
// SEND MAIL by PHP MAILER
$mail = new PHPMailer(true);
$mail->isSMTP(); // Use SMTP
$mail->CharSet = 'UTF-8';
$mail->Host = email_host_name; // Specify SMTP server
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Use TLS encryption
$mail->SMTPAuth = true; // Auth. SMTP
//$mail->SMTPDebug = 3; // To view debug output
$mail->Username = email; // Mail who send by PHPMailer
$mail->Password = email_outgoing_pw; // your pass mail box
$mail->SMTPSecure = email_outgoing_security; // Accept SSL
$mail->Port = email_outgoing_port; // port of your out server
$mail->setFrom(email, mail_from); // Mail to send at
$mail->addAddress($to); // Add sender
$mail->addReplyTo(email_reply_to); // Adress to reply
$mail->isHTML(true); // use HTML message
$mail->Subject = $subject;
$mail->Body = $message;
if (!empty($attachment) || $attachment != ''){
$mail->AddStringAttachment($attachment, $attachment_name, 'base64', 'application/pdf');
}
// Log email attempt
debuglog("Attempting to send email to: $to, subject: $subject");
// SEND
if( !$mail->send() ){
// render error if it is
$tab = array('error' => 'Mailer Error: '.$mail->ErrorInfo );
debuglog(json_encode($tab));
exit;
}
else{
// return true if message is send
return true;
try {
// SEND MAIL by PHP MAILER
$mail = new PHPMailer(true);
$mail->isSMTP(); // Use SMTP
$mail->CharSet = 'UTF-8';
$mail->Host = email_host_name; // Specify SMTP server
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Use TLS encryption
$mail->SMTPAuth = true; // Auth. SMTP
//$mail->SMTPDebug = 3; // To view debug output
$mail->Username = email; // Mail who send by PHPMailer
$mail->Password = email_outgoing_pw; // your pass mail box
$mail->SMTPSecure = email_outgoing_security; // Accept SSL
$mail->Port = email_outgoing_port; // port of your out server
debuglog("SMTP Config - Host: " . email_host_name . ", Port: " . email_outgoing_port . ", Security: " . email_outgoing_security);
$mail->setFrom(email, mail_from); // Mail to send at
$mail->addAddress($to); // Add sender
$mail->addReplyTo(email_reply_to); // Adress to reply
$mail->isHTML(true); // use HTML message
$mail->Subject = $subject;
$mail->Body = $message;
if (!empty($attachment) || $attachment != ''){
$mail->AddStringAttachment($attachment, $attachment_name, 'base64', 'application/pdf');
debuglog("Attachment added: $attachment_name");
}
// SEND
if( !$mail->send() ){
// render error if it is
$tab = array('error' => 'Mailer Error: '.$mail->ErrorInfo );
debuglog("Email send failed: " . json_encode($tab));
return false;
}
else{
// return true if message is send
debuglog("Email sent successfully to: $to");
return true;
}
} catch (Exception $e) {
debuglog("PHPMailer Exception: " . $e->getMessage());
return false;
}
}
@@ -479,13 +492,13 @@ function removeGiftCart($pdo, $orderID){
function generateInvoice($invoice_cust,$orderID,$user_language){
//Variables
$customer_email = htmlspecialchars($invoice_cust['customer']['email'] ?? '', ENT_QUOTES);
$invoice_customer_email = htmlspecialchars($invoice_cust['customer']['email'] ?? '', ENT_QUOTES);
//Generate invoice
ob_start();
include dirname(__FILE__).'/custom/email/order-invoice-template.php';
$order_invoice_template = ob_get_clean();
return array($order_invoice_template,$customer_email,$orderId);
return array($order_invoice_template,$invoice_customer_email,$orderID);
}
function freeShipment($price, $type){
@@ -613,13 +626,23 @@ function sortProducts(array $products, string $field, string $direction = 'asc')
return $products;
}
function highlightedProducts($clientsecret,$categoryID,$range, $subtitle){
function highlightedProducts($categoryID, $range, $subtitle, $catalog, $categories){
include './custom/translations/translations_'.strtoupper($_SESSION['country_code']).'.php';
//GET CATALOG DATA
$products = ioAPIv2('/v2/catalog/category='.$categoryID,'',$clientsecret);
$products = json_decode($products,true);
//GET CATALOG DATA FROM CACHE
// Build product IDs that belong to this category
$product_ids_in_category = [];
foreach ($categories as $cat) {
if ($cat['rowID'] == $categoryID && isset($cat['product_id'])) {
$product_ids_in_category[] = $cat['product_id'];
}
}
// Filter products by category
$products = array_filter($catalog, function($product) use ($product_ids_in_category) {
return in_array($product['rowID'], $product_ids_in_category);
});
//RANDOM SORT
$products = sortProducts($products, 'random');
@@ -664,13 +687,23 @@ function highlightedProducts($clientsecret,$categoryID,$range, $subtitle){
return $section ;
}
function highlightedProducts2($clientsecret,$categoryID,$range, $subtitle){
function highlightedProducts2($categoryID, $range, $subtitle, $catalog, $categories){
include './custom/translations/translations_'.strtoupper($_SESSION['country_code']).'.php';
//GET CATALOG DATA
$products = ioAPIv2('/v2/catalog/category='.$categoryID,'',$clientsecret);
$products = json_decode($products,true);
//GET CATALOG DATA FROM CACHE
// Build product IDs that belong to this category
$product_ids_in_category = [];
foreach ($categories as $cat) {
if ($cat['rowID'] == $categoryID && isset($cat['product_id'])) {
$product_ids_in_category[] = $cat['product_id'];
}
}
// Filter products by category
$products = array_filter($catalog, function($product) use ($product_ids_in_category) {
return in_array($product['rowID'], $product_ids_in_category);
});
//RANDOM SORT
$products = sortProducts($products, 'random');
@@ -730,6 +763,74 @@ function debuglog($error){
error_log($test, 3, $filelocation);
}
//------------------------------------------
// Get Cached Data from File (24-hour refresh)
//------------------------------------------
function getCachedData($api_endpoint, $cache_filename, $token){
$cache_file = './cache/' . $cache_filename;
$cache_age_limit = 24 * 60 * 60; // 24 hours in seconds
// Check if cache file exists and is fresh (less than 24 hours old)
if (file_exists($cache_file) && (time() - filemtime($cache_file)) < $cache_age_limit) {
// Return cached data from JSON file
$json_data = file_get_contents($cache_file);
return json_decode($json_data, true);
}
// Cache is stale or doesn't exist - attempt to refresh
try {
$response = ioAPIv2($api_endpoint, '', $token);
$data = json_decode($response, true);
if (!empty($data) && is_array($data)) {
// Successfully fetched new data - write to cache file as JSON
$cache_content = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
// Ensure cache directory exists
if (!is_dir('./cache')) {
mkdir('./cache', 0755, true);
}
// Attempt to write cache file
if (@file_put_contents($cache_file, $cache_content, LOCK_EX) === false) {
// Write failed - log error and fall back to existing cache
debuglog('Cache write failed for ' . $cache_filename . ' - using existing cache');
if (file_exists($cache_file)) {
$json_data = file_get_contents($cache_file);
return json_decode($json_data, true);
}
// No existing cache - return fresh data anyway
return $data;
}
return $data;
} else {
// API call failed - log error and fall back to existing cache
debuglog('API call failed for ' . $api_endpoint . ' - using existing cache');
if (file_exists($cache_file)) {
$json_data = file_get_contents($cache_file);
return json_decode($json_data, true);
}
// No existing cache and API failed - return empty array
return [];
}
} catch (Exception $e) {
// Exception occurred - log and fall back to existing cache
debuglog('Exception in getCachedData for ' . $cache_filename . ': ' . $e->getMessage());
if (file_exists($cache_file)) {
$json_data = file_get_contents($cache_file);
return json_decode($json_data, true);
}
return [];
}
}
//------------------------------------------
// Retrieve all $_GET from URL
//------------------------------------------

View File

@@ -27,9 +27,9 @@ $view .= '
// ++++++++++++++++++++++++++++++
// Include highlighted Products
// ++++++++++++++++++++++++++++++
$view .= highlightedProducts2($clientsecret,category_id_highlighted_products_1, ($highlight_2 ?? 'highlight 2'),'');
$view .= highlightedProducts2(category_id_highlighted_products_1, ($highlight_2 ?? 'highlight 2'), '', $GLOBALS['cached_catalog'], $GLOBALS['cached_categories']);
$view .= highlightedProducts($clientsecret,category_id_highlighted_products_2, ($highlight_2 ?? 'highlight 2'),'');
$view .= highlightedProducts(category_id_highlighted_products_2, ($highlight_2 ?? 'highlight 2'), '', $GLOBALS['cached_catalog'], $GLOBALS['cached_categories']);
$view .= '

112
index.php
View File

@@ -19,44 +19,98 @@ include './custom/settings/config.php';
include './custom/settings/settings.php';
include 'functions.php';
//TRANSLATION FILE LOCATION
if (isset($_GET['language']) && $_GET['language'] !=''){
//INCLUDE LANGUAGE FILE
$file_language = './custom/translations/translations_'.strtoupper($_GET['language']).'.php';
if (file_exists($file_language)){
include $file_language; //Include the code
//DEFINE LANGUAGE
$_SESSION['country_code'] = trim($_GET['language']);
}
else {
include './custom/translations/translations_NL.php';
//DEFINE LANGUAGE
$_SESSION['country_code'] = language_code;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
// Debug functions
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
if (debug){
set_error_handler(function($errno, $errstr, $errfile, $errline) {
debuglog("PHP ERROR [$errno]: $errstr in $errfile on line $errline");
return false;
});
set_exception_handler(function($exception) {
debuglog("PHP EXCEPTION: " . $exception->getMessage() . " in " . $exception->getFile() . " on line " . $exception->getLine());
});
}
//------------------------------------------
// Languages supported
//------------------------------------------
$supportedLanguages = ['US', 'NL', 'DE', 'ES','FR'];
//------------------------------------------
// Determine language to use
//------------------------------------------
// Session language expires after 30 days (adjust as needed)
$session_expiry_days = 30;
// Check if language session has expired
if (isset($_SESSION['country_code_timestamp'])) {
$days_passed = (time() - $_SESSION['country_code_timestamp']) / (60 * 60 * 24);
if ($days_passed > $session_expiry_days) {
unset($_SESSION['country_code']);
unset($_SESSION['country_code_timestamp']);
}
}
elseif(isset($_SESSION['country_code'])){
$file_language = './custom/translations/translations_'.strtoupper($_SESSION['country_code']).'.php';
if (file_exists($file_language)){
include $file_language; //Include the code
}
else {
include './custom/translations/translations_NL.php';
}
// Detect browser language first
$browser_lang = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? strtoupper(substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2)) : country_default;
if (isset($_GET['language']) && $_GET['language'] != '') {
$selected_lang = strtoupper(trim($_GET['language']));
} elseif (isset($_SESSION['country_code'])) {
$selected_lang = strtoupper($_SESSION['country_code']);
} else {
include './custom/translations/translations_NL.php';
//DEFINE LANGUAGE
$_SESSION['country_code'] = language_code;
$selected_lang = in_array($browser_lang, $supportedLanguages) ? $browser_lang : country_default;
}
// Load translation file
$file_language = './custom/translations/translations_'.$selected_lang.'.php';
if (file_exists($file_language)) {
include $file_language;
$_SESSION['country_code'] = $selected_lang;
$_SESSION['country_code_timestamp'] = time(); // Store timestamp when language is set
} else {
include './custom/translations/translations_'.strtoupper(country_default).'.php';
$_SESSION['country_code'] = country_default;
$_SESSION['country_code_timestamp'] = time();
}
$pdo = pdo_connect_mysql();
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
//LOGIN TO API
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
$data = json_encode(array("clientID" => clientID, "clientsecret" => clientsecret), JSON_UNESCAPED_UNICODE);
$responses = ioAPIv2('/v2/authorization', $data,'');
//Decode Payload
if (!empty($responses)){$responses = json_decode($responses,true);}else{$responses = '400';}
$clientsecret = $responses['token'];
// Token refresh buffer: refresh token 5 minutes (300 seconds) before expiry
$token_refresh_buffer = 300;
// Check if API token exists and is still valid
if (!isset($_SESSION['api_token']) || !isset($_SESSION['api_token_expires']) || time() >= ($_SESSION['api_token_expires'] - $token_refresh_buffer)) {
// Token missing, expired, or about to expire - get new token
$data = json_encode(array("clientID" => clientID, "clientsecret" => clientsecret), JSON_UNESCAPED_UNICODE);
$responses = ioAPIv2('/v2/authorization', $data,'');
//Decode Payload
if (!empty($responses)){$responses = json_decode($responses,true);}else{$responses = '400';}
if (isset($responses['token']) && isset($responses['token_valid'])) {
// Store token and expiry timestamp in session
$_SESSION['api_token'] = $responses['token'];
$_SESSION['api_token_expires'] = strtotime($responses['token_valid']);
$clientsecret = $responses['token'];
} else {
// Fallback for backwards compatibility
$clientsecret = $responses['token'] ?? '';
}
} else {
// Use cached token
$clientsecret = $_SESSION['api_token'];
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
//LOAD CACHED CATALOG AND CATEGORIES DATA
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
// Load catalog and categories from cache files (refreshes once per 24 hours)
$GLOBALS['cached_catalog'] = getCachedData('/v2/catalog/', 'catalog.json', $clientsecret);
$GLOBALS['cached_categories'] = getCachedData('/v2/products_categories/', 'categories.json', $clientsecret);
// Output error variable
$error = '';

BIN
log/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,672 @@
<?php
// Prevent direct access to file
defined(security_key) or exit;
// ---------------------------------------
// Defaults
// ---------------------------------------
$account = [
'account_id' => $_SESSION['account_id'] ?? '',
'email' => $_POST['email'] ?? '',
'first_name' => $_POST['first_name'] ?? '',
'last_name' => $_POST['last_name'] ?? '',
'address_street' => $_POST['address_street'] ?? '',
'address_city' => $_POST['address_city'] ?? '',
'address_state' => $_POST['address_state'] ?? '',
'address_zip' => $_POST['address_zip'] ?? '',
'address_country' => $_POST['address_country'] ?? '',
'address_phone' => $_POST['address_phone'] ?? ''
];
$products_in_cart = isset($_SESSION['cart']) ? $_SESSION['cart'] : [];
$subtotal = 0.00;
$total = 0.00;
$shippingtotal = 0.00;
$discounttotal = 0.00;
$taxtotal = 0.00;
$tax_rate = '';
$weighttotal = 0;
$shipping_methods = [];
$checkout_input = [
"selected_country" => isset($_POST['address_country']) ? $_POST['address_country'] : (isset($account['address_country']) ? $account['address_country'] : 21) ,
"selected_shipment_method" => isset($_POST['shipping_method']) ? $_POST['shipping_method'] : '',
"business_type" => 'b2c',
"discount_code" => isset($_SESSION['discount']) ? $_SESSION['discount'] : ''
];
// Error array, output errors on the form
$errors = [];
// ---------------------------------------------
// End defaults --------------------------------
// ---------------------------------------------
// Redirect the user if the shopping cart is empty
if (empty($_SESSION['cart'])) {
header('Location: ' . url('index.php?page=cart'));
exit;
}
// Check if user is logged in
if (isset($_SESSION['account_loggedin'])) {
$api_url = '/v2/identity/userkey='.$_SESSION['account_id'];
$account = ioAPIv2($api_url,'',$clientsecret);
if (!empty($account)){$account = json_decode($account,true);}
$account = $account[0];
//RESET ACCOUNT_ID
$account['account_id'] = $account['userkey'];
}
// Update discount code
if (isset($_POST['discount_code']) && !empty($_POST['discount_code'])) {
$_SESSION['discount'] = $_POST['discount_code'];
} else if (isset($_POST['discount_code']) && empty($_POST['discount_code']) && isset($_SESSION['discount'])) {
unset($_SESSION['discount']);
}
//-------------------------------
// If there are products in cart handle the checkout
//-------------------------------
if ($products_in_cart) {
// First, calculate cart to get initial totals (without shipping)
$initial_payload = json_encode(array("cart" => $products_in_cart, "checkout_input" => $checkout_input), JSON_UNESCAPED_UNICODE);
$initial_cart = ioAPIv2('/v2/checkout/',$initial_payload,$clientsecret);
$initial_cart = json_decode($initial_cart,true);
// Get initial totals for shipping method calculation
$initial_subtotal = $initial_cart['totals']['subtotal'] ?? 0;
$initial_weighttotal = $initial_cart['totals']['weighttotal'] ?? 0;
// Now retrieve shipping methods with correct totals
$shipping_methods = ioAPIv2('/v2/shipping/list=methods&country='.$checkout_input['selected_country'].'&price_total='.$initial_subtotal.'&weight_total='.$initial_weighttotal,'',$clientsecret);
$shipping_methods = json_decode($shipping_methods,true);
// If no shipping method is selected and shipping methods are available, select the first one as default
if (empty($checkout_input['selected_shipment_method']) && !empty($shipping_methods) && count($shipping_methods) > 0) {
$checkout_input['selected_shipment_method'] = $shipping_methods[0]['id'];
}
// Recalculate shopping_cart with selected shipping method
$payload = json_encode(array("cart" => $products_in_cart, "checkout_input" => $checkout_input), JSON_UNESCAPED_UNICODE);
$products_in_cart = ioAPIv2('/v2/checkout/',$payload,$clientsecret);
$products_in_cart = json_decode($products_in_cart,true);
//GET SPECIFIC TOTALS FROM API RESULTS
$subtotal = $products_in_cart['totals']['subtotal'];
$shippingtotal = $products_in_cart['totals']['shippingtotal'];
$discounttotal = $products_in_cart['totals']['discounttotal'];
$taxtotal = $products_in_cart['totals']['taxtotal'];
$tax_rate = $products_in_cart['totals']['tax_rate'];
$weighttotal = $products_in_cart['totals']['weighttotal'];
$total = $products_in_cart['totals']['total'];
// Redirect the user if the shopping cart is empty
if (empty($products_in_cart)) {
header('Location: ' . url('index.php?page=cart'));
exit;
}
//-------------------------------
// END Checkout handler
//-------------------------------
}
//-------------------------------
//Place order
//-------------------------------
// Make sure when the user submits the form all data was submitted and shopping cart is not empty
if (isset($_POST['method'], $_POST['first_name'], $_POST['last_name'], $_POST['address_street'], $_POST['address_city'], $_POST['address_state'], $_POST['address_zip'], $_POST['address_country'], $_POST['address_phone'], $_SESSION['cart']) && !isset($_POST['update'])) {
$account_id = null;
// If the user is already logged in
if (isset($_SESSION['account_loggedin'])) {
// Account logged-in, update the user's details
$payload = json_encode(
array(
"language" => $_SESSION['country_code'],
"first_name" => $_POST['first_name'],
"last_name" => $_POST['last_name'],
"address_street" => $_POST['address_street'],
"address_city" => $_POST['address_city'],
"address_state" => $_POST['address_state'],
"address_zip" => $_POST['address_zip'],
"address_country" => $_POST['address_country'],
"address_phone" => $_POST['address_phone'],
"userkey" => $_SESSION['account_id']), JSON_UNESCAPED_UNICODE);
$account_update = ioAPIv2('/v2/identity/',$payload,$clientsecret);
$account_update = json_decode($account_update,true);
$account_id = $account['account_id'] = $_SESSION['account_id'];
} else if (isset($_POST['email'], $_POST['password'], $_POST['cpassword']) && filter_var($_POST['email'], FILTER_VALIDATE_EMAIL) && !empty($_POST['password']) && !empty($_POST['cpassword'])) {
// User is not logged in, check if the account already exists with the email they submitted
// Check if the account exists
$account = ioAPIv2('/v2/identity/email='.$_POST['email'],'',$clientsecret);
$account = json_decode($account,true);
if ($account) {
// Email exists, user should login instead...
$errors[] = $error_account_name;
}
if (strlen($_POST['password']) > 20 || strlen($_POST['password']) < 5) {
// Password must be between 5 and 20 characters long.
$errors[] = $error_account_password_rules;
}
if ($_POST['password'] != $_POST['cpassword']) {
// Password and confirm password fields do not match...
$errors[] = $error_account_password_match;
}
if (!$errors) {
// Account doesnt exist, create new account
$payload = json_encode(
array(
"email" => $_POST['email'],
"password" => $_POST['password'],
"language" => $_SESSION['country_code'],
"first_name" => $_POST['first_name'],
"last_name" => $_POST['last_name'],
"address_street" => $_POST['address_street'],
"address_city" => $_POST['address_city'],
"address_state" => $_POST['address_state'],
"address_zip" => $_POST['address_zip'],
"address_country" => $_POST['address_country'],
"address_phone" => $_POST['address_phone']), JSON_UNESCAPED_UNICODE);
$account = ioAPIv2('/v2/identity/',$payload,$clientsecret);
$account= json_decode($account,true);
$account_id = $account['account_id'] = $account['accountID'];
if ($account && isset($account['accountID'])) {
//SEND VERIFICATION EMAIL
include dirname(__FILE__).'/custom/email/email_template_register.php';
$register_mail = $message;
send_mail_by_PHPMailer($account['identity'], $subject, $register_mail,'', '');
$register_error = 'Email send to verify your account';
}
}
} else if (account_required) {
$errors[] = $error_account;
}
if (!$errors && $products_in_cart) {
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Process checkout => add payment_method to checkout_input array
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
$checkout_input['payment_method'] = $_POST['method'];
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Calculate shopping_cart based on session
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
$payload = json_encode(array("cart" => $_SESSION['cart'], "checkout_input" => $checkout_input, "customer_details" => $account), JSON_UNESCAPED_UNICODE);
$place_order = ioAPIv2('/v2/placeorder/',$payload,$clientsecret);
$place_order = json_decode($place_order,true);
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Check if transaction is succesfull and send order confirmation to customer
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
if ($place_order['error'] == '' && $place_order['id'] != ''){
// Push purchase event to dataLayer
if (isset($place_order['products_checked-out']) && is_array($place_order['products_checked-out'])) {
$productIds = [];
$totalQuantity = 0;
$products = [];
foreach ($place_order['products_checked-out'] as $p) {
if (is_array($p)) {
$productIds[] = $p['id'] ?? '';
$totalQuantity += $p['quantity'] ?? 0;
$products[] = [
'id' => $p['id'] ?? '',
'name' => $p['meta']['name'] ?? '',
'price' => $p['options_price'] ?? 0,
'quantity' => $p['quantity'] ?? 0
];
}
}
echo "<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'event': 'purchase',
'ecommerce': {
'purchase': {
'actionField': {
'id': '" . $place_order['transaction_id'] . "',
'revenue': '" . $place_order['payment_amount'] . "',
'tax': '" . $place_order['taxtotal'] . "',
'shipping': '" . $place_order['shippingtotal'] . "'
},
'products': " . json_encode($products) . "
}
},
'content_type': 'product',
'content_ids': " . json_encode($productIds) . ",
'value': " . floatval($place_order['payment_amount']) . ",
'currency': 'EUR',
'num_items': " . $totalQuantity . "
});
</script>";
}
//SEND CONFIRMATION TO CUSTOMER
send_order_details_email(
$account['email'],
$place_order['products_checked-out'],
$account['first_name'],
$account['last_name'],
$account['address_street'],
$account['address_city'],
$account['address_state'],
$account['address_zip'],
$account['address_country'],
$place_order['subtotal'],
$place_order['discounttotal'],
$place_order['shippingtotal'],
$place_order['taxtotal'],
$place_order['payment_amount'],
$place_order['transaction_id']
);
//Disable giftcard
if (isset($_SESSION['discount'])){
if (preg_match("/[#][0-9]/", $_SESSION['discount']) == 1){
useGiftCart($pdo, $_SESSION['discount']);
}
}
// Authenticate the user
if ($account_id != null) {
// Log the user in with the details provided
session_regenerate_id();
$_SESSION['account_loggedin'] = TRUE;
$_SESSION['account_id'] = $account_id;
$_SESSION['account_role'] = $account ? $account['profile'] : 0;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Pay on delivery = 2
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
if (pay_on_delivery_enabled && $place_order['payment_method'] == 2){
header('Location: ' . url('index.php?page=placeorder'));
exit;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Mollie = 3 ++++++++++++++++++++++++++++++++++++++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
if (mollie_enabled && $_POST['method'] == 3) {
try {
/*
* Initialize the Mollie API library with your API key.
*
* See: https://www.mollie.com/dashboard/developers/api-keys
*/
require "initialize.php";
/*
* Generate a unique order id for this example. It is important to include this unique attribute
* in the redirectUrl (below) so a proper return page can be shown to the customer.
*/
$orderId = $place_order['transaction_id'];
$value = number_format($place_order['payment_amount'],2,'.','');
/*
* Determine the url parts to these example files.
*/
$protocol = isset($_SERVER['HTTPS']) && strcasecmp('off', $_SERVER['HTTPS']) !== 0 ? "https" : "http";
$hostname = $_SERVER['HTTP_HOST'];
$path = dirname($_SERVER['REQUEST_URI'] ?? $_SERVER['PHP_SELF']);
/*
* Payment parameters:
* amount Amount in EUROs.
* description Description of the payment.
* redirectUrl Redirect location. The customer will be redirected there after the payment.
* webhookUrl Webhook location, used to report when the payment changes state.
* metadata Custom metadata that is stored with the payment.
*/
if (rewrite_url){
$redirectURL = $protocol.'://'.$hostname.$path.'placeorder/'.$orderId;
}else{
$redirectURL = $protocol.'://'.$hostname.$path.'index.php?page=placeorder&order_id='.$orderId;
}
$payment = $mollie->payments->create([
"amount" => [
"currency" => "EUR",
"value" => "{$value}", // You must send the correct number of decimals, thus we enforce the use of strings
],
"description" => "Order #{$orderId}",
"redirectUrl" => "$redirectURL",
"webhookUrl" => "{$protocol}://{$hostname}{$path}webhook.php",
"metadata" => [
"order_id" => $orderId,
],
]);
/*
* Send the customer off to complete the payment.
* This request should always be a GET, thus we enforce 303 http response code
*/
// Send customer to checkout
header("Location: " . $payment->getCheckoutUrl(), true, 303);
} catch (\Mollie\Api\Exceptions\ApiException $e) {
echo "API call failed: " . htmlspecialchars($e->getMessage());
}
exit;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// PayPal Payment = 1 +++++++++++++++++++++++++++++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
if (paypal_enabled && $_POST['method'] == 1) {
//Process Payment
require_once __DIR__."/lib/paypal/paypal.php";
$base = PAYPAL_URL;
$id = PAYPAL_CLIENT_ID;
$secret = PAYPAL_CLIENT_SECRET;
//init input
$order = $place_order['transaction_id'];
$price = number_format($place_order['payment_amount'],2,'.','');
$currency = "EUR";
//make payment
$paypal = new paypalCurl();
$paypal->init($id,$secret,$base);
$result = $paypal->makePaymentURL($order,$price,$currency);
if ($result->status === true) {
header("location:". $result->url);
die;
}
else { //raise error
echo $result->msg;
die;
}
}
} else {
foreach ($place_order['error'] as $error){
$errors[] = $error;
}
}
}
}
//-------------------------------
// END PLACE ORDER
//-------------------------------
$terms_link = url('index.php?page=termsandconditions');
$privacy_link = url('index.php?page=privacy');
$view = template_header(($checkout_header ?? 'Checkout'),'');
// Push initiateCheckout event to dataLayer
if (isset($products_in_cart['cart_details']['products']) && is_array($products_in_cart['cart_details']['products']) && count($products_in_cart['cart_details']['products']) > 0) {
$productIds = array_map(function($p) { return $p['id']; }, $products_in_cart['cart_details']['products']);
$totalQuantity = array_sum(array_map(function($p) { return $p['quantity']; }, $products_in_cart['cart_details']['products']));
$view .= '<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
"event": "initiateCheckout",
"ecommerce": {
"checkout": {
"actionField": {
"step": 1
},
"products": ' . json_encode(array_map(function($p) {
return [
'id' => $p['id'],
'name' => $p['meta']['name'],
'price' => $p['options_price'],
'quantity' => $p['quantity']
];
}, $products_in_cart['cart_details']['products'])) . '
}
},
"content_type": "product",
"content_ids": ' . json_encode($productIds) . ',
"value": ' . $total . ',
"currency": "EUR",
"num_items": ' . $totalQuantity . '
});
</script>';
}
$view .= '
<div class="checkout content-wrapper">
<h1>'.$h1_checkout.'</h1>';
if (!empty($errors) || count($errors) > 0){
$view .= '<p class="error">'.implode('<br>', $errors).'</p>';
}
if (!isset($_SESSION['account_loggedin'])){
$view .= '<p>'.$account_available.' <a href="'.url('index.php?page=myaccount').'">'.$account_log_in.'</a></p>';
}
$view .= '
<form action="" method="post">
<div class="container">
<div class="shipping-details">x
<div id="dropin-container"></div>
<h2>'.$payment_method.'</h2>
<div class="payment-methods">';
if (mollie_enabled){
$view .= ' <input id="mollie-ideal" type="radio" name="method" value="3" '. ((mollie_default)? 'checked':'') .'>
<label for="mollie-ideal">
<img src="./custom/assets/wero.svg" style="width: 100px;" alt="'.$payment_method_1.'">
</label>';
$view .= ' <input id="mollie-card" type="radio" name="method" value="3">
<label for="mollie-card">
<img src="./custom/assets/mastercard.png" style="width: 50px;" alt="'.$payment_method_1.'">
<img src="./custom/assets/visa.png" style="width: 50px;" alt="'.$payment_method_1.'">
</label>';
}
if (paypal_enabled){
$view .= ' <input id="paypal" type="radio" name="method" value="1" '. ((paypal_default)? 'checked':'') .'>
<label for="paypal"><img src="https://www.paypalobjects.com/webstatic/mktg/Logo/pp-logo-100px.png" alt="PayPal Logo"></label>';
}
if (pay_on_delivery_enabled){
$view .= ' <input id="payondelivery" type="radio" name="method" value="2" '. ((pay_on_delivery_default)? 'checked':'') .' >
<label for="payondelivery">'.$payment_method_2.'</label>';
}
$view .= ' </div>';
if (!isset($_SESSION['account_loggedin'])){
$view .= '
<h2>'.$account_create_email.'</h2>
<label for="email">'.$account_create_email.' *</label>
<input type="email" name="email" id="email" placeholder="'.$account_create_email.'" class="form-field" required>
<h2 onclick="togglePasswordSection()" style="cursor: pointer;">'.$account_create.((!account_required) ? $account_create_optional : '').' <span id="indicator">▼</span></h2>
<div id="password-section" style="display: none;">
<label for="password">'.$account_create_password.'</label>
<input type="password" name="password" id="password" placeholder="'.$account_create_password.'" class="form-field" autocomplete="new-password">
<label for="cpassword">'.$account_create_password_confirm.'</label>
<input type="password" name="cpassword" id="cpassword" placeholder="'.$account_create_password_confirm.'" class="form-field" autocomplete="new-password">
</div>
';
}
$view .= '
<h2>'.$h2_Shipping_details.'</h2>
<div class="row1">
<label for="first_name">'.$shipping_first_name.' *</label>
<input type="text" value="'.htmlspecialchars($account['first_name'], ENT_QUOTES).'" name="first_name" id="first_name" placeholder="'.$shipping_first_name.'" class="form-field" required>
</div>
<div class="row2">
<label for="last_name">'.$shipping_last_name.' *</label>
<input type="text" value="'.htmlspecialchars($account['last_name'], ENT_QUOTES).'" name="last_name" id="last_name" placeholder="'.$shipping_last_name.'" class="form-field" required>
</div>
<label for="address_street">'.$shipping_address.' *</label>
<input type="text" value="'.htmlspecialchars($account['address_street'], ENT_QUOTES).'" name="address_street" id="address_street" placeholder="'.$shipping_address.'" class="form-field" required>
<label for="address_city">'.$shipping_city.' *</label>
<input type="text" value="'.htmlspecialchars($account['address_city'], ENT_QUOTES).'" name="address_city" id="address_city" placeholder="'.$shipping_city.'" class="form-field" required>
<div class="row1">
<label for="address_state">'.$shipping_state.'</label>
<input type="text" value="'.htmlspecialchars($account['address_state'], ENT_QUOTES).'" name="address_state" id="address_state" placeholder="'.$shipping_state.'" class="form-field">
</div>
<div class="row2">
<label for="address_zip">'.$shipping_zip.' *</label>
<input type="text" value="'.htmlspecialchars($account['address_zip'], ENT_QUOTES).'" name="address_zip" id="address_zip" placeholder="'.$shipping_zip.'" class="form-field" required>
</div>
<label for="address_phone">'.$shipping_phone.' *</label>
<input type="text" value="'.htmlspecialchars(($account['address_phone'] ?? ''), ENT_QUOTES).'" name="address_phone" id="address_phone" placeholder="'.$shipping_phone.'" class="form-field" required>
<label for="address_country">'.$shipping_country.' *</label>
<select name="address_country" class="ajax-update form-field" required>';
foreach($countries_in_scope as $key => $value){
$view .= ' <option value="'.$key.'" '.($key==(isset($_SESSION['account_loggedin']) ? $account['address_country'] : 21) ? ' selected' : '').'>'.(${$value} ?? $value).'</option>';
}
$view .= ' </select>
</div>
<div class="cart-details">
<h2>'.$h2_shoppingcart.'</h2>
<table>';
foreach($products_in_cart['cart_details']['products'] as $product){
$view .= ' <tr>
<td><img src="'.img_url.$product['meta']['img'].'" width="35" height="35" alt="'.$product['meta']['name'].'"></td>
<td>'.$product['quantity'].' x '.$product['meta']['name'].'</td>
<td class="price">'.currency_code.''.number_format($product['options_price'] * $product['quantity'],2).'</td>
</tr>';
}
$view .= ' </table>
<div class="discount-code">
<input type="text" class="ajax-update form-field" name="discount_code" placeholder="'.$discount_label.'" value="'.(isset($_SESSION['discount']) ? $_SESSION['discount'] : '').'">
<span class="result">';
if (isset($_SESSION['discount'], $products_in_cart['totals']['discounttotal'])){
$view .= $products_in_cart['totals']['discount_message'];
}
$view .= ' </span>
</div>
<div class="shipping-methods-container">';
if (isset($shipping_methods) && count($shipping_methods) > 0){
$view .= ' <div class="shipping-methods">
<h3>'.$h3_shipping_method.' *</h3>';
foreach($shipping_methods as $method){
$view .= ' <div class="shipping-method">
<input type="radio" class="ajax-update" id="sm'.$method['id'].'" name="shipping_method" value="'.$method['id'].'" required'.(($checkout_input['selected_shipment_method']==$method['id'] || count($shipping_methods) == 1) ? ' checked':'').'>
<label for="sm'.$method['id'].'">'.$method['name'].' ('.currency_code.''.number_format($method['price'], 2).')</label>
</div>';
}
$view .= '</div>';
}
$view .= ' </div>
<div class="summary">
<div class="subtotal">
<span>'.$total_subtotal.'</span>
<span>'.currency_code.''.number_format($subtotal,2).'</span>
</div>
<div class="shipping">
<span>'.$total_shipping.'</span>
<span>'.currency_code.''.number_format($shippingtotal,2).'</span>
</div>';
if ($discounttotal > 0){
$view .= '<div class="discount">
<span>'.$total_discount.'</span>
<span>-'.currency_code.''.number_format(round($discounttotal, 1),2).'</span>
</div>';
}
if ($taxtotal > 0){
$view .= '<div class="vat">
<span>'.($tax_text ?? 'VAT').' <span class="alt">('.$tax_rate.')</span></span>
<span>'.currency_code.''.number_format($taxtotal,2).'</span>
</div>';
}
$view .= ' </div>
<div class="total">
<span>'.$total_total.' <span class="alt">'.$total_total_note.'</span></span><span>'.currency_code.''.number_format($total,2).'</span>
</div>
<div class="summary">
<div class="subtotal">
<span>
<input type="checkbox" id="consent" name="consent_comms" value="1">'.$order_consent_1.'</a>
</span>
</div>
<div class="subtotal">
<span>
<input type="checkbox" id="consent" name="consent" value="1" required>'.$order_consent_2.' * <a href="'.$terms_link.'" target="_blank">'.$order_consent_3.'</a> '.$order_consent_4.' <a href="'.$privacy_link.'" target="_blank">'.$order_consent_5.'</a>
</span>
</div>
</div>
<div class="buttons">
<button type="submit" name="checkout" class="checkout_btn">'.$btn_place_order.'</button>
</div>
</div>
</div>
</form>
</div>
';
echo '<script>
function togglePasswordSection() {
var section = document.getElementById(\'password-section\');
var indicator = document.getElementById(\'indicator\');
if (section.style.display === \'none\') {
section.style.display = \'block\';
indicator.textContent = \'▲\';
} else {
section.style.display = \'none\';
indicator.textContent = \'▼\';
}
}
</script>
';
$view .= template_footer();
//OUTPUT
echo $view;
?>

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,247 +0,0 @@
2025-05-01 13:26:30;/v2/authorization
2025-05-01 13:26:30;/v2/catalog/category=22
2025-05-01 13:27:06;/v2/authorization
2025-05-01 13:27:07;/v2/authorization
2025-05-01 13:27:07;/v2/catalog/category=22
2025-05-01 17:33:32;/v2/authorization
2025-05-01 17:33:32;/v2/catalog/category=22
2025-05-01 21:17:53;/v2/authorization
2025-05-01 21:17:53;/v2/catalog/category=22
2025-05-04 09:58:52;/v2/authorization
2025-05-04 09:58:52;/v2/catalog/category=22
2025-05-04 10:04:17;/v2/authorization
2025-05-04 10:04:17;/v2/authorization
2025-05-04 10:04:17;/v2/authorization
2025-05-04 10:04:17;/v2/authorization
2025-05-04 10:04:17;/v2/authorization
2025-05-04 10:04:17;/v2/catalog/category=22
2025-05-04 10:04:17;/v2/authorization
2025-05-04 10:04:17;/v2/authorization
2025-05-04 10:04:17;/v2/catalog/category=22
2025-05-04 10:04:17;/v2/authorization
2025-05-04 10:04:18;/v2/catalog/category=22
2025-05-04 10:04:18;/v2/authorization
2025-05-04 10:04:18;/v2/catalog/category=22
2025-05-04 10:04:18;/v2/authorization
2025-05-04 10:04:18;/v2/catalog/category=22
2025-05-07 15:11:15;/v2/authorization
2025-05-07 15:11:15;/v2/catalog/category=22
2025-05-07 15:12:33;/v2/authorization
2025-05-07 15:12:33;/v2/catalog/category=22
2025-05-08 19:41:48;/v2/authorization
2025-05-08 19:41:48;/v2/catalog/category=22
2025-05-08 19:42:02;/v2/authorization
2025-05-08 19:42:02;/v2/authorization
2025-05-08 19:42:02;/v2/catalog/category=22
2025-05-08 19:42:10;/v2/authorization
2025-05-08 19:42:10;/v2/categories/
2025-05-08 19:42:10;/v2/catalog/category=17
2025-05-08 19:42:24;/v2/authorization
2025-05-08 19:42:28;/v2/authorization
2025-05-08 19:42:28;/v2/identity/
2025-05-08 19:42:28;/v2/authorization
2025-05-08 19:42:28;/v2/transactions_items/account_id=d808773e1ba5292d7c640d04ed04c1fbc32cce74a83d334061
2025-05-08 19:42:28;/v2/identity/userkey=d808773e1ba5292d7c640d04ed04c1fbc32cce74a83d334061
2025-05-08 19:42:55;/v2/authorization
2025-05-08 19:42:56;/v2/catalog/category=22
2025-05-08 19:43:08;/v2/authorization
2025-05-08 19:43:08;/v2/categories/
2025-05-08 19:43:09;/v2/catalog/category=17
2025-05-08 19:43:14;/v2/authorization
2025-05-08 19:43:14;/v2/catalog/category=22
2025-05-08 19:43:19;/v2/authorization
2025-05-08 19:43:19;/v2/catalog/category=22
2025-05-08 19:43:27;/v2/authorization
2025-05-08 19:43:27;/v2/categories/
2025-05-08 19:43:27;/v2/catalog/category=17
2025-05-08 19:45:41;/v2/authorization
2025-05-08 19:45:46;/v2/authorization
2025-05-08 19:45:46;/v2/categories/
2025-05-08 19:45:46;/v2/catalog/category=17
2025-05-08 19:45:47;/v2/authorization
2025-05-08 19:45:47;/v2/catalog/category=22
2025-05-08 19:54:20;/v2/authorization
2025-05-08 19:54:21;/v2/catalog/category=22
2025-05-09 11:12:58;/v2/authorization
2025-05-09 11:12:58;/v2/catalog/category=22
2025-05-09 11:13:01;/v2/authorization
2025-05-09 11:13:01;/v2/catalog/category=22
2025-05-09 11:14:06;/v2/authorization
2025-05-09 11:14:07;/v2/catalog/category=22
2025-05-09 11:14:42;/v2/authorization
2025-05-09 11:14:42;/v2/authorization
2025-05-09 11:14:42;/v2/catalog/category=22
2025-05-09 11:14:42;/v2/catalog/category=22
2025-05-09 11:45:34;/v2/authorization
2025-05-09 11:45:34;/v2/catalog/category=22
2025-05-09 11:45:39;/v2/authorization
2025-05-09 11:45:39;/v2/catalog/category=22
2025-05-09 11:45:48;/v2/authorization
2025-05-09 11:45:48;/v2/catalog/category=22
2025-05-09 11:45:49;/v2/authorization
2025-05-09 12:56:57;/v2/authorization
2025-05-09 12:56:57;/v2/catalog/category=22
2025-05-09 13:08:28;/v2/authorization
2025-05-09 13:08:29;/v2/catalog/category=22
2025-05-09 13:44:52;/v2/authorization
2025-05-09 13:44:52;/v2/catalog/category=22
2025-05-09 13:44:55;/v2/authorization
2025-05-09 13:44:56;/v2/authorization
2025-05-09 13:44:56;/v2/catalog/category=22
2025-05-09 15:15:07;/v2/authorization
2025-05-09 15:15:07;/v2/catalog/category=22
2025-05-09 21:10:30;/v2/authorization
2025-05-09 21:10:30;/v2/catalog/category=22
2025-05-10 20:03:56;/v2/authorization
2025-05-10 20:03:56;/v2/catalog/category=22
2025-05-10 20:03:57;/v2/authorization
2025-05-10 20:03:57;/v2/catalog/category=22
2025-05-11 03:21:55;/v2/authorization
2025-05-11 03:21:55;/v2/catalog/category=22
2025-05-11 03:21:57;/v2/authorization
2025-05-11 03:21:57;/v2/authorization
2025-05-11 03:21:57;/v2/catalog/category=22
2025-05-11 04:50:31;/v2/authorization
2025-05-11 04:50:31;/v2/catalog/category=22
2025-05-11 20:21:12;/v2/authorization
2025-05-11 20:21:12;/v2/catalog/category=22
2025-05-12 10:07:48;/v2/authorization
2025-05-12 10:07:49;/v2/catalog/category=22
2025-05-13 09:08:36;/v2/authorization
2025-05-13 09:08:36;/v2/catalog/category=22
2025-05-13 09:08:37;/v2/authorization
2025-05-13 09:08:37;/v2/authorization
2025-05-13 09:08:38;/v2/catalog/category=22
2025-05-13 09:08:40;/v2/authorization
2025-05-13 09:08:40;/v2/authorization
2025-05-13 09:08:46;/v2/catalog/category=22
2025-05-13 09:08:47;/v2/authorization
2025-05-13 09:08:47;/v2/authorization
2025-05-13 09:08:47;/v2/catalog/category=22
2025-05-13 09:08:47;/v2/authorization
2025-05-13 09:08:48;/v2/authorization
2025-05-13 09:08:48;/v2/catalog/category=22
2025-05-13 09:08:50;/v2/authorization
2025-05-13 09:08:50;/v2/authorization
2025-05-13 09:08:50;/v2/catalog/category=22
2025-05-13 09:08:52;/v2/authorization
2025-05-13 09:08:52;/v2/authorization
2025-05-13 09:08:52;/v2/catalog/category=22
2025-05-13 09:08:53;/v2/authorization
2025-05-13 09:08:53;/v2/authorization
2025-05-13 09:08:53;/v2/catalog/category=22
2025-05-13 09:08:55;/v2/authorization
2025-05-13 09:08:57;/v2/authorization
2025-05-13 09:08:57;/v2/authorization
2025-05-13 09:08:57;/v2/catalog/category=22
2025-05-13 09:08:58;/v2/authorization
2025-05-13 09:08:58;/v2/authorization
2025-05-13 09:08:59;/v2/catalog/category=22
2025-05-13 09:08:59;/v2/authorization
2025-05-13 09:08:59;/v2/authorization
2025-05-13 09:08:59;/v2/catalog/category=22
2025-05-13 13:14:28;/v2/authorization
2025-05-13 13:14:28;/v2/catalog/category=22
2025-05-13 13:14:41;/v2/authorization
2025-05-13 13:14:42;/v2/catalog/product_id=thomasII_navy_blue
2025-05-13 13:14:42;/v2/products_media/product_id=60
2025-05-13 13:15:02;/v2/authorization
2025-05-13 13:15:03;/v2/catalog/category=22
2025-05-13 13:15:42;/v2/authorization
2025-05-13 13:15:42;/v2/catalog/product_id=thomasII_navy_blue
2025-05-13 13:15:42;/v2/products_media/product_id=60
2025-05-13 13:15:56;/v2/authorization
2025-05-13 13:15:56;/v2/authorization
2025-05-13 13:15:56;/v2/catalog/category=22
2025-05-13 13:16:10;/v2/authorization
2025-05-13 13:16:10;/v2/catalog/category=22
2025-05-13 13:16:25;/v2/authorization
2025-05-13 13:16:26;/v2/authorization
2025-05-13 13:16:26;/v2/catalog/category=22
2025-05-13 13:16:36;/v2/authorization
2025-05-13 13:16:37;/v2/authorization
2025-05-13 13:16:37;/v2/catalog/category=22
2025-05-13 13:16:43;/v2/authorization
2025-05-13 13:16:43;/v2/catalog/product_id=thomasII_ice_blue
2025-05-13 13:16:43;/v2/products_media/product_id=61
2025-05-13 13:18:40;/v2/authorization
2025-05-13 13:18:40;/v2/catalog/category=22
2025-05-13 14:05:58;/v2/authorization
2025-05-13 14:05:58;/v2/authorization
2025-05-13 14:05:58;/v2/authorization
2025-05-13 14:05:59;/v2/catalog/category=22
2025-05-13 14:05:59;/v2/authorization
2025-05-13 14:05:59;/v2/authorization
2025-05-13 14:05:59;/v2/catalog/category=22
2025-05-13 14:59:33;/v2/authorization
2025-05-13 14:59:33;/v2/catalog/category=22
2025-05-13 15:00:23;/v2/authorization
2025-05-13 15:00:23;/v2/catalog/category=22
2025-05-13 15:01:35;/v2/authorization
2025-05-13 15:01:36;/v2/catalog/category=22
2025-05-13 15:49:43;/v2/authorization
2025-05-13 15:49:43;/v2/catalog/category=22
2025-05-13 15:56:55;/v2/authorization
2025-05-13 15:56:56;/v2/catalog/category=22
2025-05-13 15:57:01;/v2/authorization
2025-05-13 15:57:01;/v2/catalog/product_id=thomasII_dolphin_gray
2025-05-13 15:57:01;/v2/products_media/product_id=63
2025-05-13 15:57:03;/v2/authorization
2025-05-13 15:57:03;/v2/catalog/category=22
2025-05-13 15:57:30;/v2/authorization
2025-05-13 15:57:30;/v2/catalog/product_id=thomasII_racing_green
2025-05-13 15:57:30;/v2/products_media/product_id=62
2025-05-13 15:57:38;/v2/authorization
2025-05-13 15:57:38;/v2/catalog/category=22
2025-05-13 15:57:58;/v2/authorization
2025-05-13 15:57:58;/v2/categories/
2025-05-13 15:57:58;/v2/catalog/category=17
2025-05-13 15:58:06;/v2/authorization
2025-05-13 15:58:06;/v2/categories/
2025-05-13 15:58:06;/v2/catalog/category=23
2025-05-13 15:58:32;/v2/authorization
2025-05-13 15:58:32;/v2/categories/
2025-05-13 15:58:32;/v2/catalog/category=17
2025-05-13 15:58:48;/v2/authorization
2025-05-13 15:58:48;/v2/catalog/category=22
2025-05-13 17:39:53;/v2/authorization
2025-05-13 17:39:53;/v2/catalog/category=22
2025-05-13 18:07:39;/v2/authorization
2025-05-13 18:07:39;/v2/catalog/category=22
2025-05-13 22:58:35;/v2/authorization
2025-05-13 22:58:35;/v2/catalog/category=22
2025-05-15 22:34:09;/v2/authorization
2025-05-15 22:34:09;/v2/catalog/category=22
2025-05-21 14:46:27;/v2/authorization
2025-05-21 14:46:27;/v2/catalog/category=22
2025-05-21 14:46:28;/v2/authorization
2025-05-21 14:46:28;/v2/authorization
2025-05-21 14:46:29;/v2/catalog/category=22
2025-05-21 14:46:30;/v2/authorization
2025-05-21 14:46:30;/v2/catalog/product_id=thomasII_dolphin_gray
2025-05-21 14:46:30;/v2/products_media/product_id=63
2025-05-21 14:46:30;/v2/authorization
2025-05-21 14:46:30;/v2/authorization
2025-05-21 14:46:30;/v2/catalog/category=22
2025-05-21 14:46:31;/v2/authorization
2025-05-21 14:46:31;/v2/authorization
2025-05-21 14:46:31;/v2/catalog/category=22
2025-05-21 20:44:30;/v2/authorization
2025-05-21 20:44:30;/v2/catalog/category=22
2025-05-22 17:16:25;/v2/authorization
2025-05-22 17:16:25;/v2/catalog/category=22
2025-05-22 17:16:27;/v2/authorization
2025-05-22 17:16:27;/v2/catalog/category=22
2025-05-22 17:16:28;/v2/authorization
2025-05-22 17:16:28;/v2/catalog/category=22
2025-05-22 17:16:28;/v2/authorization
2025-05-22 17:16:29;/v2/catalog/category=22
2025-05-23 06:16:09;/v2/authorization
2025-05-23 06:16:09;/v2/catalog/category=22
2025-05-23 06:16:12;/v2/authorization
2025-05-23 06:16:13;/v2/authorization
2025-05-23 06:16:13;/v2/catalog/category=22
2025-05-23 22:27:40;/v2/authorization
2025-05-23 22:27:40;/v2/catalog/category=22
2025-05-25 20:27:10;/v2/authorization
2025-05-25 20:27:11;/v2/catalog/category=22

608
log/logging.php Normal file
View File

@@ -0,0 +1,608 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>System Logging</title>
<style>
:root {
--primary-green: #22c55e;
--white: #ffffff;
--gray-50: #f9fafb;
--gray-100: #f3f4f6;
--gray-200: #e5e7eb;
--gray-300: #d1d5db;
--gray-500: #6b7280;
--gray-600: #4b5563;
--gray-700: #374151;
--gray-900: #111827;
--space-xs: 0.25rem;
--space-sm: 0.5rem;
--space-md: 0.75rem;
--space-lg: 1rem;
--space-xl: 1.5rem;
--radius-md: 0.375rem;
--radius-lg: 0.5rem;
--font-size-sm: 0.875rem;
--font-size-base: 1rem;
--font-size-lg: 1.125rem;
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
background: var(--gray-50);
color: var(--gray-900);
line-height: 1.6;
}
.content-area {
padding: var(--space-xl);
max-width: 1400px;
margin: 0 auto;
}
.w-full {
width: 100%;
}
.card {
background: var(--white);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-md);
border: 1px solid var(--gray-200);
}
.card__header {
padding: var(--space-xl);
}
.card__title {
font-size: 1.875rem;
font-weight: 700;
color: var(--gray-900);
margin-bottom: var(--space-sm);
}
.card__subtitle {
font-size: var(--font-size-base);
color: var(--gray-500);
}
.btn {
border: 1px solid var(--gray-300);
background: var(--white);
color: var(--gray-700);
cursor: pointer;
transition: all 0.2s ease;
font-weight: 500;
}
.btn:hover {
background: var(--gray-50);
border-color: var(--gray-400);
}
.btn--secondary {
background: var(--gray-100);
}
.btn--sm {
padding: var(--space-sm) var(--space-md);
font-size: var(--font-size-sm);
}
</style>
</head>
<body>
<?php
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// POST HANDLER - Delete all logs
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
$delete_message = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_all_logs'])) {
$logs_dir = __DIR__ . '/';
$deleted_count = 0;
if (is_dir($logs_dir)) {
$files = scandir($logs_dir);
foreach ($files as $file) {
if (preg_match('/\.txt$/', $file)) {
if (unlink($logs_dir . $file)) {
$deleted_count++;
}
}
}
}
$delete_message = "Successfully deleted $deleted_count log file(s).";
// Redirect to clear POST data
header("Location: " . strtok($_SERVER["REQUEST_URI"], '?') . "?deleted=$deleted_count");
exit;
}
// Show delete confirmation message
if (isset($_GET['deleted'])) {
$delete_message = "Successfully deleted " . intval($_GET['deleted']) . " log file(s).";
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// GET HANDLER
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Get selected log file from query parameter
$selected_log = $_GET['log'] ?? '';
// Scan logs directory for all log files
// Use __DIR__ to get current directory of this script
$logs_dir = __DIR__ . '/';
$log_files = [];
if (is_dir($logs_dir)) {
$files = scandir($logs_dir);
foreach ($files as $file) {
if (preg_match('/\.txt$/', $file) && is_file($logs_dir . $file)) {
// Extract date from filename (last 2 digits before .txt)
$date = '00'; // Default date
if (preg_match('/_(\d{2})\.txt$/', $file, $matches)) {
$date = $matches[1];
}
$log_files[] = [
'filename' => $file,
'date' => $date,
'path' => $logs_dir . $file,
'size' => filesize($logs_dir . $file)
];
}
}
}
// Sort by date descending, then by filename
usort($log_files, function($a, $b) {
if ($a['date'] === $b['date']) {
return strcmp($b['filename'], $a['filename']);
}
return $b['date'] <=> $a['date'];
});
// Load selected log content
$contents = '';
if ($selected_log && file_exists($logs_dir . $selected_log)) {
$contents = file_get_contents($logs_dir . $selected_log);
} elseif (!empty($log_files)) {
// Default to most recent log
$contents = file_get_contents($log_files[0]['path']);
$selected_log = $log_files[0]['filename'];
} else {
$contents = 'No application log files found.';
}
$filelocation_webserver = '/var/www/vhosts/morvalwatches.com/logs/'.$_SERVER['HTTP_HOST'].'/access_ssl_log';
if (file_exists($filelocation_webserver)){
$contents_webserver = file_get_contents($filelocation_webserver);
} else {$contents_webserver = 'No webserver log file found.';}
?>
<!-- Main Content Area --><?php
// Display delete message if exists
if ($delete_message) {
echo '<div style="
position: fixed;
top: var(--space-lg);
right: var(--space-lg);
background: var(--primary-green);
color: var(--white);
padding: var(--space-md) var(--space-lg);
border-radius: var(--radius-md);
box-shadow: var(--shadow-md);
z-index: 1000;
font-weight: 500;
" id="delete-notification">
✓ ' . htmlspecialchars($delete_message) . '
</div>';
}
echo '
<div class="content-area">
<div class="w-full">
<!-- Tab Navigation -->
<div style="
background: var(--white);
border-radius: var(--radius-lg) var(--radius-lg) 0 0;
border: 1px solid var(--gray-200);
border-bottom: none;
padding: 0;
margin-bottom: 0;
box-shadow: var(--shadow-sm);
">
<div style="
display: flex;
gap: 0;
padding: var(--space-sm);
background: var(--gray-50);
border-radius: var(--radius-lg) var(--radius-lg) 0 0;
">
<button
class="tab-button active"
onclick="switchTab(\'app\', this)"
style="
flex: 1;
padding: var(--space-md) var(--space-xl);
border: none;
background: var(--primary-green);
color: var(--white);
border-radius: var(--radius-md);
cursor: pointer;
font-weight: 600;
font-size: var(--font-size-base);
transition: all 0.2s ease;
margin-right: var(--space-sm);
box-shadow: var(--shadow-sm);
"
onmouseover="if(!this.classList.contains(\'active\')) { this.style.background=\'var(--gray-200)\'; this.style.color=\'var(--gray-700)\'; }"
onmouseout="if(!this.classList.contains(\'active\')) { this.style.background=\'var(--gray-100)\'; this.style.color=\'var(--gray-600)\'; }"
>
Application Log
</button>
<button
class="tab-button"
onclick="switchTab(\'webserver\', this)"
style="
flex: 1;
padding: var(--space-md) var(--space-xl);
border: none;
background: var(--gray-100);
color: var(--gray-600);
border-radius: var(--radius-md);
cursor: pointer;
font-weight: 600;
font-size: var(--font-size-base);
transition: all 0.2s ease;
box-shadow: var(--shadow-sm);
"
onmouseover="if(!this.classList.contains(\'active\')) { this.style.background=\'var(--gray-200)\'; this.style.color=\'var(--gray-700)\'; }"
onmouseout="if(!this.classList.contains(\'active\')) { this.style.background=\'var(--gray-100)\'; this.style.color=\'var(--gray-600)\'; }"
>
Webserver Log
</button>
</div>
</div>
<!-- Tab Content Container -->
<div style="
background: var(--white);
border: 1px solid var(--gray-200);
border-radius: 0 0 var(--radius-lg) var(--radius-lg);
padding: var(--space-xl);
box-shadow: var(--shadow-md);
min-height: 70vh;
">
<!-- Application Log Tab -->
<div id="tab-app" class="tab-content active" style="display: block;">
<div style="
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--space-lg);
padding-bottom: var(--space-md);
border-bottom: 1px solid var(--gray-200);
">
<div style="flex: 1;">
<h3 style="
margin: 0;
color: var(--gray-900);
font-size: var(--font-size-lg);
font-weight: 600;
">Application Log</h3>
<div style="
margin-top: var(--space-sm);
display: flex;
align-items: center;
gap: var(--space-sm);
">
<label style="
color: var(--gray-600);
font-size: var(--font-size-sm);
font-weight: 500;
">Select Log File:</label>
<select
id="log-file-selector"
onchange="loadLogFile(this.value)"
style="
padding: var(--space-xs) var(--space-md);
border: 1px solid var(--gray-300);
border-radius: var(--radius-md);
font-size: var(--font-size-sm);
background: var(--white);
color: var(--gray-700);
cursor: pointer;
min-width: 250px;
"
>';
foreach ($log_files as $log) {
$selected = ($log['filename'] === $selected_log) ? 'selected' : '';
$size_kb = round($log['size'] / 1024, 2);
echo '<option value="'.htmlspecialchars($log['filename']).'" '.$selected.'>'.htmlspecialchars($log['filename']).' ('.$size_kb.' KB)</option>';
}
echo '</select>
</div>
</div>
<div style="display: flex; gap: var(--space-sm);">
<button
onclick="refreshLog(\'app\')"
class="btn btn--secondary btn--sm"
style="
padding: var(--space-sm) var(--space-md);
font-size: var(--font-size-sm);
display: flex;
align-items: center;
gap: var(--space-xs);
"
>
🔄 Refresh
</button>
<button
onclick="clearLogContent(\'app-log\')"
class="btn btn--secondary btn--sm"
style="
padding: var(--space-sm) var(--space-md);
font-size: var(--font-size-sm);
display: flex;
align-items: center;
gap: var(--space-xs);
"
>
🗑️ Clear View
</button>
<form method="POST" onsubmit="return confirmDeleteAll()" style="margin: 0; display: inline;">
<button
type="submit"
name="delete_all_logs"
class="btn btn--sm"
style="
padding: var(--space-sm) var(--space-md);
font-size: var(--font-size-sm);
background: #ef4444;
color: var(--white);
border: none;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
align-items: center;
gap: var(--space-xs);
"
onmouseover="this.style.background=\'#dc2626\'"
onmouseout="this.style.background=\'#ef4444\'"
>
🗑️ Delete All Logs
</button>
</form>
</div>
</div>
<textarea
id="app-log"
readonly
style="
width: 100%;
min-height: 60vh;
padding: var(--space-lg);
border: 1px solid var(--gray-300);
border-radius: var(--radius-md);
font-family: \'Courier New\', monospace;
font-size: 12px;
line-height: 1.4;
background: var(--gray-900);
color: var(--gray-100);
resize: vertical;
white-space: pre-wrap;
overflow-wrap: break-word;
"
placeholder="No log content available..."
>'.htmlspecialchars($contents).'</textarea>
</div>
<!-- Webserver Log Tab -->
<div id="tab-webserver" class="tab-content" style="display: none;">
<div style="
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--space-lg);
padding-bottom: var(--space-md);
border-bottom: 1px solid var(--gray-200);
">
<div>
<h3 style="
margin: 0;
color: var(--gray-900);
font-size: var(--font-size-lg);
font-weight: 600;
">Webserver Access Log</h3>
<p style="
margin: var(--space-xs) 0 0;
color: var(--gray-500);
font-size: var(--font-size-sm);
">File: '.$filelocation_webserver.'</p>
</div>
<div style="display: flex; gap: var(--space-sm);">
<button
onclick="refreshLog(\'webserver\')"
class="btn btn--secondary btn--sm"
style="
padding: var(--space-sm) var(--space-md);
font-size: var(--font-size-sm);
display: flex;
align-items: center;
gap: var(--space-xs);
"
>
🔄 Refresh
</button>
<button
onclick="clearLogContent(\'webserver-log\')"
class="btn btn--secondary btn--sm"
style="
padding: var(--space-sm) var(--space-md);
font-size: var(--font-size-sm);
display: flex;
align-items: center;
gap: var(--space-xs);
"
>
🗑️ Clear View
</button>
</div>
</div>
<textarea
id="webserver-log"
readonly
style="
width: 100%;
min-height: 60vh;
padding: var(--space-lg);
border: 1px solid var(--gray-300);
border-radius: var(--radius-md);
font-family: \'Courier New\', monospace;
font-size: 12px;
line-height: 1.4;
background: var(--gray-900);
color: var(--gray-100);
resize: vertical;
white-space: pre-wrap;
overflow-wrap: break-word;
"
placeholder="No log content available..."
>'.htmlspecialchars($contents_webserver).'</textarea>
</div>
</div>
</div>
</div>
'; ?>
<script>
// Confirm delete all logs
function confirmDeleteAll() {
return confirm('⚠️ WARNING: This will permanently delete ALL log files in the logs directory.\n\nAre you absolutely sure you want to continue?');
}
// Auto-hide delete notification
document.addEventListener('DOMContentLoaded', function() {
const notification = document.getElementById('delete-notification');
if (notification) {
setTimeout(() => {
notification.style.opacity = '0';
notification.style.transition = 'opacity 0.5s ease';
setTimeout(() => notification.remove(), 500);
}, 3000);
}
});
// Tab switching functionality
function switchTab(tabName, clickedButton) {
// Hide all tab contents
const tabContents = document.querySelectorAll('.tab-content');
tabContents.forEach(content => {
content.style.display = 'none';
});
// Remove active class and reset styles for all tab buttons
const tabButtons = document.querySelectorAll('.tab-button');
tabButtons.forEach(button => {
button.classList.remove('active');
button.style.background = 'var(--gray-100)';
button.style.color = 'var(--gray-600)';
});
// Show the selected tab content
const selectedTab = document.getElementById('tab-' + tabName);
if (selectedTab) {
selectedTab.style.display = 'block';
}
// Add active class and style to clicked button
clickedButton.classList.add('active');
clickedButton.style.background = 'var(--primary-green)';
clickedButton.style.color = 'var(--white)';
}
// Load selected log file
function loadLogFile(filename) {
if (filename) {
const url = new URL(window.location.href);
url.searchParams.set('log', filename);
window.location.href = url.toString();
}
}
// Refresh log functionality
function refreshLog(logType) {
const button = event.target.closest('button');
const originalText = button.innerHTML;
// Show loading state
button.innerHTML = '⏳ Refreshing...';
button.disabled = true;
// Simulate refresh (reload the page to get fresh content)
setTimeout(() => {
window.location.reload();
}, 500);
}
// Clear log content from view
function clearLogContent(textareaId) {
const textarea = document.getElementById(textareaId);
if (textarea) {
if (confirm('Clear the log content from view? (This won\'t delete the actual log file)')) {
textarea.value = '';
// Show notification
showNotification('Log view cleared', 'info');
}
}
}
// Show notification function
// Add CSS animations
const style = document.createElement('style');
style.textContent = `
@keyframes slideInRight {
from { opacity: 0; transform: translateX(100%); }
to { opacity: 1; transform: translateX(0); }
}
@keyframes slideOutRight {
from { opacity: 1; transform: translateX(0); }
to { opacity: 0; transform: translateX(100%); }
}
`;
document.head.appendChild(style);
// Auto-scroll to bottom of logs when page loads
document.addEventListener('DOMContentLoaded', function() {
const activeTextarea = document.querySelector('.tab-content.active textarea');
if (activeTextarea && activeTextarea.value.trim()) {
activeTextarea.scrollTop = activeTextarea.scrollHeight;
}
});
// Handle checkbox values (existing functionality)
document.querySelectorAll("input[type='checkbox']").forEach(checkbox => {
checkbox.onclick = () => checkbox.value = checkbox.checked ? 'true' : 'false';
});
</script>
</body>
</html>

5463
log/main.css Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,209 +0,0 @@
<?php
$h2_brand_name_1 = 'MorvalWatches';
$h2_brand_name_2 = 'eine Marke mit einer Geschichte';
$h2_brand_visit = 'Besuche unsere Kollektion';
$h2_brand_wow = 'Morval vereint eine einzigartige Kombination aus minimalistischem Design, Schweizer Qualität und niederländischer Fertigung.Wir bieten Ihnen eine Uhr, die zu jedem Anlass getragen werden kann.';
$h1_content_top = 'Unsere Uhrenkollektion';
$product_count_1 = 'Produkt';
$product_count_2 = 'e';
$main_filter_category = 'Kategorie';
$main_category = 'Alle';
$main_filter_sort = 'Sortieren';
$sort1 = 'A-Z';
$sort2 = 'Z-A';
$sort3 = 'Neueste';
$sort4 = 'Älteste';
$sort5 = 'Preis hoch - niedrig';
$sort6 = 'Preis niedrig - hoch';
$free_delivery = 'kostenloser Versand';
$non_free_delivery = 'kostenloser Versand ab';
$breadcrum_products = 'Kollektion';
$product_quantity = 'Menge';
$product_on_stock = 'Auf Lager';
$out_of_stock_notify = 'Benachrichtigen Sie mich';
$out_of_stock_notify_2 = 'Besuchen Sie uns @';
$out_of_stock = 'Nicht auf Lager';
$add_to_basket = 'In den Warenkorb';
$h1_cart_name = 'Warenkorb';
$h2_cart_suggestions = 'Vorschläge';
$h2_cart_sample_product = 'Muster';
$tr_product = 'Produkt';
$tr_price = 'Preis';
$tr_quantity = 'Menge';
$tr_total = 'Gesamt';
$total_subtotal = 'Zwischensumme';
$total_note = '(Versandkosten werden während des Bezahlvorgangs berechnet)';
$total_vat = 'MwSt';
$total_shipping = 'Versand';
$total_shipping_note = '(Versand inbegriffen)';
$total_discount = 'Rabatt';
$total_total = 'Gesamt';
$total_total_note = 'MwSt inbegriffen';
$btn_emptycart = 'leeren';
$btn_update = 'Aktualisieren';
$btn_checkout = 'Zur Kasse';
$navigation_back_to_store = 'zurück zur Kollektion';
$cart_message_empty = 'Sie haben keine Produkte in Ihrem Warenkorb';
$error_account_name = 'Konto existiert bereits.';
$error_account_password_rules = 'Das Passwort muss zwischen 5 und 20 Zeichen lang sein.';
$error_account_password_match = 'Passwörter stimmen nicht überein.';
$error_account = 'Kontoerstellung erforderlich.';
$h1_checkout = 'Zur Kasse';
$account_available = 'Haben Sie bereits ein Konto?';
$account_log_in = 'Anmelden';
$account_create = 'Konto erstellen';
$account_create_optional = '(optional)';
$account_create_email = 'E-Mail';
$account_create_password = 'Passwort';
$account_create_password_confirm = 'Passwort bestätigen';
$h2_Shipping_details = 'Versanddetails';
$h3_shipping_method = 'Versandmethode';
$shipping_first_name = 'Vorname';
$shipping_last_name = 'Nachname';
$shipping_address = 'Adresse';
$shipping_city = 'Stadt';
$shipping_state = 'Region/Bundesland';
$shipping_zip = 'PLZ';
$shipping_country = 'Land';
$shipping_phone = 'Telefon';
$payment_method = 'Zahlungsmethode';
$payment_method_1 = 'Lastschrift (NL/BE-Kunden)';
$payment_method_2 = 'Zahlung bei Lieferung';
$h2_shoppingcart = 'Warenkorb';
$discount_label = 'Rabattcode';
$discount_message = 'Rabattcode angewendet!';
$discount_error_1 = 'Falscher Rabattcode!';
$discount_error_2 = 'Rabattcode abgelaufen!';
$order_consent_1 = 'Ich möchte E-Mail-Kommunikation über MorvalWatches Neuigkeiten, Produkte und Dienstleistungen erhalten';
$order_consent_2 = 'Ich stimme zu';
$order_consent_3 = 'AGB';
$btn_place_order = 'Bestellen';
$h1_order_succes_message = 'Ihre Bestellung wurde aufgegeben';
$order_succes_message = 'Vielen Dank für Ihre Bestellung! Wir werden Sie per E-Mail mit Ihren Bestelldetails kontaktieren.';
$error_myaccount = 'Falsche E-Mail/Passwort!';
$h1_login = 'Anmelden';
$h1_register = 'Registrieren';
$h1_myaccount = 'Mein Konto';
$h2_menu = 'Menü';
$menu_orders = 'Bestellungen';
$menu_downloads = 'Downloads';
$h2_myorders = 'Meine Bestellungen';
$myorders_message = 'Sie haben keine Bestellungen';
$myorders_order = 'Bestellung';
$myorders_date = 'Datum';
$myorders_status = 'Status';
$myorders_shipping = 'Versand';
$myorders_total = 'Gesamt';
$h2_mydownloads = 'Meine Downloads';
$mydownloads_message = 'Sie haben keine Downloads';
$mydownloads_product = 'Produkt';
$h2_settings = 'Einstellungen';
$settings_email = 'E-Mail';
$settings_new_password = 'Neues Passwort';
$btn_settings_save = 'Speichern';
$age_consent_h4 = 'Lass uns dein Alter überprüfen';
$age_consent_text = 'Um MorvalWatches zu besuchen, müssen Sie 18 Jahre oder älter sein.';
$age_consent_btn_allow = 'Zustimmen';
$age_consent_btn_deny = 'Ablehnen';
$maintenanceMode_h4 = 'Webshop befindet sich in Wartung';
$maintenanceMode_text = 'Unser Webshop befindet sich in Wartung. Wir freuen uns, Sie bald wieder zu sehen';
$maintenanceMode_btn = 'OK';
$subject_order_notification = 'MorvalWatches - Sie haben eine neue Bestellung erhalten!';
$subject_new_order = 'MorvalWatches - Bestelldetails';
$subject_out_of_stock = 'MorvalWatches - Nicht auf Lager';
$home_text = 'Startseite';
$products_text = 'Kollektion';
$about_text = 'Über uns';
$myaccount_text = 'Konto';
$social_punch_line = 'Verbinden Sie sich mit Morval über unsere Social-Media-Kanäle';
$privacy_text = 'Datenschutz';
$terms_text = 'Allgemeine Geschäftsbedingungen';
$faq_text = 'Häufig gestellte Fragen';
$order_email_title = 'MorvalWatches - Bestellung';
$order_email_message_1 = 'Vielen Dank für Ihre Bestellung';
$order_email_message_2 = 'Ihre Bestellung ist eingegangen und wird derzeit bearbeitet. Die Details zu Ihrer Bestellung finden Sie unten.';
$order_email_information = 'Ihre Details';
$h2_about_1 = 'Über Morval';
$about_header_1 = 'Über uns';
$about_1_p = 'Morval Watches wurde 2023 von Ralph van Wezel gegründet. Ralph ist Krankenhausapotheker und hat eine Faszination für Technologie. In seiner Arbeit ist er bestrebt, Medikamente verfügbar zu machen, die einen Unterschied für den Patienten machen. Die Herstellung eines Medikaments erfordert Wissen, Präzision, Genauigkeit, Technik, Qualität und Handwerkskunst. Hierin liegt die Ähnlichkeit mit der Herstellung einer hochwertigen Automatikuhr. Ralph hat sich zum Ziel gesetzt, eine Uhr zu entwickeln, die mit den renommierten Marken konkurrieren kann, aber zu einem akzeptablen Preis verkauft wird.';
$about_header_2 = 'Über unsere Uhren';
$about_2_p = 'Eine Morval-Uhr ist von den Vintage-Modellen und dem minimalistischen Design skandinavischer Uhren inspiriert. Dank der Farbvariationen von Zifferblatt und Armband kann eine Morval-Uhr zu jedem Anlass getragen werden sowohl als Sport- als auch als elegante Uhr. Morval-Uhren erfüllen höchste Qualitätsanforderungen und können mit den bekannten Schweizer Marken mithalten. Die Komponenten stammen von renommierten Herstellern aus Europa und dem Ausland. Eine Morval verfügt über ein Schweizer Kaliber (STP), das für seine zuverlässige Qualität bekannt ist. Die Montage erfolgt in Amsterdam durch anerkannte Uhrmacher, und jede Uhr wird einer umfassenden Qualitätskontrolle hinsichtlich Funktionalität und Ästhetik unterzogen. Die Uhr wird manuell eingestellt und geprüft, um Abweichungen zu minimieren. Morval steht für ein hervorragendes Preis-Leistungs-Verhältnis! Mit dem Kauf einer Morval-Uhr erhalten Sie garantiert einen zeitlosen Zeitmesser, der Jahrzehnte hält. Viel Liebe zum Detail wurde auf Details gelegt, wie zum Beispiel ein gebürstetes Gehäuse aus Edelstahl 316, Superluminova auf den Zeigern, entspiegeltes Glas und ein stufenlos verstellbares Lederarmband. Dies spiegelt den luxuriösen Auftritt der Marke wider. Mit einer Morval-Uhr besitzen Sie eine einzigartige, robuste, stilvolle und zeitlose Uhr, die Generationen überdauert!';
$about_header_3 = 'Über Morval';
$about_morval_text = 'Lesen Sie mehr über die Geschichte von Morval';
$h2_about_morval_1 = 'Die Geschichte von Morval';
$h2_about_morval_2 = '';
$about_morval_header_1 = '';
$about_morval_header_2 = '';
$about_morval_header_3 = '';
$about_morval_2_p = 'Als die Trümmer beseitigt waren, blieb dieser große, leere Platz wie eine Wunde in den Herzen der Einwohner zurück. Drei Jahre später errichtete die Gemeinde einen kleinen Glockenturm, an dem die drei Glocken aufgehängt wurden, die für den Abriss heruntergelassen worden waren. Dank der Unterstützung der Bewohner der 1930er Jahre sind sie noch heute lebendig und läuten noch immer, um jedes glückliche oder unglückliche Ereignis zu markieren, wie wir es einst taten.';
$about_morval_3_p = 'Als die Trümmer beseitigt waren, blieb dieser große, leere Platz wie eine Wunde in den Herzen der Einwohner zurück. Drei Jahre später errichtete die Gemeinde einen kleinen Glockenturm, an dem die drei Glocken aufgehängt wurden, die für den Abriss heruntergelassen worden waren. Dank der Unterstützung der Einwohner der 1930er Jahre sind sie noch immer lebendig und läuten noch immer, um jedes glückliche oder unglückliche Ereignis zu markieren, wie wir es einst taten. Dank ihnen hat Morval seinen verlorenen Glockenturm nicht vergessen.';
$invoice_morval_subject = 'Morval Uhren - Rechnung';
$place_order_header = 'Bestellung aufgeben';
$checkout_header = 'Kasse';
$tax_text = 'Mehrwertsteuer';
$h2_cart_samples = 'Proben';
$products_filters_h2 = 'Filter';
$btn_filter = 'Filter';
$sort = 'Sortieren';
$order_number_text = 'Befehl';
$order_date_text = 'Datum';
$tr_options = 'Optionen';
$order_invoice_text = 'Rechnung';
$invoice_payment_paid_text = 'Der Gesamtbetrag dieser Rechnung ist bezahlt';
$highlight_1 = 'Sammlung';
$highlight_2 = 'Sammlung';
$home_timeless = 'Zeitlos';
$home_timeless_text = 'Morval-Uhren sind einzigartige, robuste, stilvolle und zeitlose Zeitmesser, die Generationen überdauern!';
$shop_action = 'Jetzt kaufen';
$home_quality = 'Qualität';
$home_quality_text = 'Morval Uhren erfüllen höchste Qualitätsansprüche und können mit den bekannten Schweizer Marken mithalten. Die Komponenten stammen von renommierten Herstellern aus Europa und dem Ausland. Eine Morval verfügt über ein Schweizer Kaliber (STP), das für seine zuverlässige Qualität bekannt ist.';
$home_price = 'Preis';
$home_price_text = 'Morval steht für ein hervorragendes Preis-Leistungs-Verhältnis';
$shopping_cart_header = 'Warenkorb';
$about_3_p = 'Morval hat seinen Namen vom Nachnamen eines von Ralphs Großeltern. Das Logo ist inspiriert vom Denkmal in der Stadt Morval in Nordfrankreich, das aus den Überresten einer Kirche und den drei Glocken des Turms errichtet wurde.';
$newuser_credential_text_1 = 'Ihr Konto wurde mit dem Benutzernamen erstellt';
$newuser_credential_text_2 = 'Klicken Sie bitte auf die Schaltfläche unten, um Ihre Registrierung abzuschließen.';
$verify_account = 'Konto verifizieren';
$newuser_signature = ' Mit freundlichen Grüße,';
$newuser_signature_name = 'MorvalUhren';
$changeuser_credential_text_1 = 'Klicken Sie bitte auf die Schaltfläche unten, um das Passwort Ihres Kontos zurückzusetzen.';
$changeuser_signature = ' Mit freundlichen Grüße,';
$changeuser_signature_name = 'MorvalUhren';
$bracelet_dark = 'Schwarz';
$bracelet_blue = 'Dunkelblau';
$bracelet_dark_brown = 'Dunkelbraun';
$bracelet_light_brown = 'Hellbraun';
$bracelet_steel = 'Stahl';
$MWTH1NB_description = '<p>Die Thomas-I strahlt Eleganz und Raffinesse aus. Klassische Maße kombiniert mit dezenten Details im Zifferblatt machen sie zu einer besonderen Automatikuhr, die zu jedem Anlass getragen werden kann.</p><h3><b>Technische Daten</b></h3><ul><li>Gehäusegröße: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 mit 26 Steinen</li><li>Gangreserve: 40 h</li><li>Ischronismus: &lt; 10 Sek./Tag</li><li>Lünette: Polierter Edelstahl (316L)</li><li>Wasserdicht: 50 Meter (5 ATM)</li><li>Zifferblatt: Sonnenstrahlen-Muster</li><li>Datum: Arabische Zahlen (Tag)</li><li>Leuchtmasse: Superluminova (Blau)</li><li>Glas: Saphirglas mit Antireflexbeschichtung</li><li>Gehäuseboden: Verschraubt, gebürsteter Edelstahl mit Saphirglas</li><li>Armband (Stahl): Gebürsteter und polierter 316L Edelstahl</li><li>Armband (Leder): Handgefertigtes italienisches Kalbsleder</li><li>Schließe: Faltschließe für höchsten Komfort</li><li>Verpackung: Blaue Box mit Zertifikat und Bedienungsanleitung.</li></ul>';
$MWTH2NB_description = '<p>Die Thomas-II bietet einen Blick auf das schlagende Herz der Schweizer Uhr. Sie steht für die Präzision und Perfektion, mit der die Zeit angezeigt wird.</p><h3><b>Technische Daten</b></h3><ul><li>Gehäusegröße: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 mit 26 Steinen</li><li>Gangreserve: 40 h</li><li>Ischronismus: &lt; 10 Sek./Tag</li><li>Lünette: Gebürsteter Edelstahl (316L)</li><li>Wasserdicht: 50 Meter (5 ATM)</li><li>Zifferblatt: Sonnenstrahlen-Muster</li><li>Leuchtmasse: Superluminova (Blau)</li><li>Glas: Saphirglas mit Antireflexbeschichtung</li><li>Gehäuseboden: Verschraubt, gebürsteter Edelstahl mit Saphirglas</li><li>Armband (Stahl): Gebürsteter und polierter 316L Edelstahl</li><li>Armband (Leder): Handgefertigtes italienisches Kalbsleder</li><li>Schließe: Faltschließe für höchsten Komfort</li><li>Verpackung: Blaue Box mit Zertifikat und Bedienungsanleitung.</li></ul>';
$MWTH2IB_description = '<p>Die Thomas-II bietet einen Blick auf das schlagende Herz der Schweizer Uhr. Sie steht für die Präzision und Perfektion, mit der die Zeit angezeigt wird.</p><h3><b>Technische Daten</b></h3><ul><li>Gehäusegröße: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 mit 26 Steinen</li><li>Gangreserve: 40 h</li><li>Ischronismus: &lt; 10 Sek./Tag</li><li>Lünette: Gebürsteter Edelstahl (316L)</li><li>Wasserdicht: 50 Meter (5 ATM)</li><li>Zifferblatt: Sonnenstrahlen-Muster</li><li>Leuchtmasse: Superluminova (Blau)</li><li>Glas: Saphirglas mit Antireflexbeschichtung</li><li>Gehäuseboden: Verschraubt, gebürsteter Edelstahl mit Saphirglas</li><li>Armband (Stahl): Gebürsteter und polierter 316L Edelstahl</li><li>Armband (Leder): Handgefertigtes italienisches Kalbsleder</li><li>Schließe: Faltschließe für höchsten Komfort</li><li>Verpackung: Blaue Box mit Zertifikat und Bedienungsanleitung.</li></ul>';
$MWTH2RG_description = '<p>Die Thomas-II bietet einen Blick auf das schlagende Herz der Schweizer Uhr. Sie steht für die Präzision und Perfektion, mit der die Zeit angezeigt wird.</p><h3><b>Technische Daten</b></h3><ul><li>Gehäusegröße: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 mit 26 Steinen</li><li>Gangreserve: 40 h</li><li>Ischronismus: &lt; 10 Sek./Tag</li><li>Lünette: Gebürsteter Edelstahl (316L)</li><li>Wasserdicht: 50 Meter (5 ATM)</li><li>Zifferblatt: Sonnenstrahlen-Muster</li><li>Leuchtmasse: Superluminova (Blau)</li><li>Glas: Saphirglas mit Antireflexbeschichtung</li><li>Gehäuseboden: Verschraubt, gebürsteter Edelstahl mit Saphirglas</li><li>Armband (Stahl): Gebürsteter und polierter 316L Edelstahl</li><li>Armband (Leder): Handgefertigtes italienisches Kalbsleder</li><li>Schließe: Faltschließe für höchsten Komfort</li><li>Verpackung: Blaue Box mit Zertifikat und Bedienungsanleitung.</li></ul>';
$MWTH2DG_description = '<p>Die Thomas-II bietet einen Blick auf das schlagende Herz der Schweizer Uhr. Sie steht für die Präzision und Perfektion, mit der die Zeit angezeigt wird.</p><h3><b>Technische Daten</b></h3><ul><li>Gehäusegröße: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 mit 26 Steinen</li><li>Gangreserve: 40 h</li><li>Ischronismus: &lt; 10 Sek./Tag</li><li>Lünette: Gebürsteter Edelstahl (316L)</li><li>Wasserdicht: 50 Meter (5 ATM)</li><li>Zifferblatt: Sonnenstrahlen-Muster</li><li>Leuchtmasse: Superluminova (Blau)</li><li>Glas: Saphirglas mit Antireflexbeschichtung</li><li>Gehäuseboden: Verschraubt, gebürsteter Edelstahl mit Saphirglas</li><li>Armband (Stahl): Gebürsteter und polierter 316L Edelstahl</li><li>Armband (Leder): Handgefertigtes italienisches Kalbsleder</li><li>Schließe: Faltschließe für höchsten Komfort</li><li>Verpackung: Blaue Box mit Zertifikat und Bedienungsanleitung.</li></ul>';
$MWTH2G_description = '<p>Die Thomas-II bietet einen Blick auf das schlagende Herz der Schweizer Uhr. Sie steht für die Präzision und Perfektion, mit der die Zeit angezeigt wird.</p><h3><b>Technische Daten</b></h3><ul><li>Gehäusegröße: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 mit 26 Steinen</li><li>Gangreserve: 40 h</li><li>Ischronismus: &lt; 10 Sek./Tag</li><li>Lünette: Gebürsteter Edelstahl (316L)</li><li>Wasserdicht: 50 Meter (5 ATM)</li><li>Zifferblatt: Sonnenstrahlen-Muster</li><li>Leuchtmasse: Superluminova (Blau)</li><li>Glas: Saphirglas mit Antireflexbeschichtung</li><li>Gehäuseboden: Verschraubt, gebürsteter Edelstahl mit Saphirglas</li><li>Armband (Stahl): Gebürsteter und polierter 316L Edelstahl</li><li>Armband (Leder): Handgefertigtes italienisches Kalbsleder</li><li>Schließe: Faltschließe für höchsten Komfort</li><li>Verpackung: Blaue Box mit Zertifikat und Bedienungsanleitung.</li></ul>';
$MWABRB1_description = 'Armband Handgefertigtes italienisches Kalbsleder';
$MWABRDB1_description = 'Armband Handgefertigtes italienisches Kalbsleder';
$MWABRLB1_description = 'Armband Handgefertigtes italienisches Kalbsleder';
$MWABRBL1_description = 'Armband Handgefertigtes italienisches Kalbsleder';
$MWTH1IB_description = '<p>Die Thomas-I strahlt Eleganz und Raffinesse aus. Klassische Maße kombiniert mit dezenten Details im Zifferblatt machen sie zu einer besonderen Automatikuhr, die zu jedem Anlass getragen werden kann.</p><h3><b>Technische Daten</b></h3><ul><li>Gehäusegröße: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 mit 26 Steinen</li><li>Gangreserve: 40 h</li><li>Ischronismus: &lt; 10 Sek./Tag</li><li>Lünette: Polierter Edelstahl (316L)</li><li>Wasserdicht: 50 Meter (5 ATM)</li><li>Zifferblatt: Sonnenstrahlen-Muster</li><li>Datum: Arabische Zahlen (Tag)</li><li>Leuchtmasse: Superluminova (Blau)</li><li>Glas: Saphirglas mit Antireflexbeschichtung</li><li>Gehäuseboden: Verschraubt, gebürsteter Edelstahl mit Saphirglas</li><li>Armband (Stahl): Gebürsteter und polierter 316L Edelstahl</li><li>Armband (Leder): Handgefertigtes italienisches Kalbsleder</li><li>Schließe: Faltschließe für höchsten Komfort</li><li>Verpackung: Blaue Box mit Zertifikat und Bedienungsanleitung.</li></ul>';
$MWTH1RG_description = '<p>Die Thomas-I strahlt Eleganz und Raffinesse aus. Klassische Maße kombiniert mit dezenten Details im Zifferblatt machen sie zu einer besonderen Automatikuhr, die zu jedem Anlass getragen werden kann.</p><h3><b>Technische Daten</b></h3><ul><li>Gehäusegröße: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 mit 26 Steinen</li><li>Gangreserve: 40 h</li><li>Ischronismus: &lt; 10 Sek./Tag</li><li>Lünette: Polierter Edelstahl (316L)</li><li>Wasserdicht: 50 Meter (5 ATM)</li><li>Zifferblatt: Sonnenstrahlen-Muster</li><li>Datum: Arabische Zahlen (Tag)</li><li>Leuchtmasse: Superluminova (Blau)</li><li>Glas: Saphirglas mit Antireflexbeschichtung</li><li>Gehäuseboden: Verschraubt, gebürsteter Edelstahl mit Saphirglas</li><li>Armband (Stahl): Gebürsteter und polierter 316L Edelstahl</li><li>Armband (Leder): Handgefertigtes italienisches Kalbsleder</li><li>Schließe: Faltschließe für höchsten Komfort</li><li>Verpackung: Blaue Box mit Zertifikat und Bedienungsanleitung.</li></ul>';
$MWTH1DG_description = '<p>Die Thomas-I strahlt Eleganz und Raffinesse aus. Klassische Maße kombiniert mit dezenten Details im Zifferblatt machen sie zu einer besonderen Automatikuhr, die zu jedem Anlass getragen werden kann.</p><h3><b>Technische Daten</b></h3><ul><li>Gehäusegröße: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 mit 26 Steinen</li><li>Gangreserve: 40 h</li><li>Ischronismus: &lt; 10 Sek./Tag</li><li>Lünette: Polierter Edelstahl (316L)</li><li>Wasserdicht: 50 Meter (5 ATM)</li><li>Zifferblatt: Sonnenstrahlen-Muster</li><li>Datum: Arabische Zahlen (Tag)</li><li>Leuchtmasse: Superluminova (Blau)</li><li>Glas: Saphirglas mit Antireflexbeschichtung</li><li>Gehäuseboden: Verschraubt, gebürsteter Edelstahl mit Saphirglas</li><li>Armband (Stahl): Gebürsteter und polierter 316L Edelstahl</li><li>Armband (Leder): Handgefertigtes italienisches Kalbsleder</li><li>Schließe: Faltschließe für höchsten Komfort</li><li>Verpackung: Blaue Box mit Zertifikat und Bedienungsanleitung.</li></ul>';
$MWTH1G_description = '<p>Die Thomas-I strahlt Eleganz und Raffinesse aus. Klassische Maße kombiniert mit dezenten Details im Zifferblatt machen sie zu einer besonderen Automatikuhr, die zu jedem Anlass getragen werden kann.</p><h3><b>Technische Daten</b></h3><ul><li>Gehäusegröße: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 mit 26 Steinen</li><li>Gangreserve: 40 h</li><li>Ischronismus: &lt; 10 Sek./Tag</li><li>Lünette: Polierter Edelstahl (316L)</li><li>Wasserdicht: 50 Meter (5 ATM)</li><li>Zifferblatt: Sonnenstrahlen-Muster</li><li>Datum: Arabische Zahlen (Tag)</li><li>Leuchtmasse: Superluminova (Blau)</li><li>Glas: Saphirglas mit Antireflexbeschichtung</li><li>Gehäuseboden: Verschraubt, gebürsteter Edelstahl mit Saphirglas</li><li>Armband (Stahl): Gebürsteter und polierter 316L Edelstahl</li><li>Armband (Leder): Handgefertigtes italienisches Kalbsleder</li><li>Schließe: Faltschließe für höchsten Komfort</li><li>Verpackung: Blaue Box mit Zertifikat und Bedienungsanleitung.</li></ul>';
$payment_status_0 = 'Offen';
$payment_status_1 = 'Bezahlt';
$payment_status_101 = 'Ausstehend';
$payment_status_102 = 'Fehlgeschlagen';
$payment_status_103 = 'Abgelaufen';
$payment_status_999 = 'Abgesagt';
$payment_method_3 = 'Soll/Haben';
$ad_watch_1 = 'Niederländisches Design und Schweizer Handwerkskunst';
$ad_watch_2 = 'Zeitlose Uhren, die Generationen überdauern!';
$ad_watch_btn = 'mehr lesen';
$newsletter_h2 = 'Melden Sie sich für den<br>Newsletter an';
$newsletter_p = 'Bleiben Sie mit unseren neuesten Updates, Tipps und exklusiven Angeboten auf dem Laufenden direkt in Ihrem Posteingang.';
$newsletter_confirm = 'Ich habe die Datenschutzrichtlinie gelesen und stimme ihr zu';
$newsletter_submit = 'einreichen';
$header_manufacturing = 'Schweizer Qualität und niederländische Fertigung';
$header_shipping = 'Kostenloser Versand für alle unsere Uhren';
$header_delivery = 'Schneller Service und Lieferung';
$header_rating = 'Kundenbewertung 4.7/5.0';
?>

View File

@@ -1,209 +0,0 @@
<?php
$h2_brand_name_1 = 'MorvalWatches';
$h2_brand_name_2 = 'una marca con historia';
$h2_brand_visit = 'Visite nuestra colección';
$h2_brand_wow = 'Morval reúne una combinación única de diseño minimalista, calidad suiza y fabricación holandesa.Te ofrecemos un reloj para llevar en cualquier ocasión.';
$h1_content_top = 'Nuestra colección de relojes';
$product_count_1 = 'Producto';
$product_count_2 = 's';
$main_filter_category = 'Categoría';
$main_category = 'Todos';
$main_filter_sort = 'Ordenar';
$sort1 = 'A-Z';
$sort2 = 'Z-A';
$sort3 = 'Más recientes';
$sort4 = 'Más antiguos';
$sort5 = 'Precio alto - bajo';
$sort6 = 'Precio bajo - alto';
$free_delivery = 'envío gratis';
$non_free_delivery = 'envío gratis a partir de';
$breadcrum_products = 'Colección';
$product_quantity = 'Cantidad';
$product_on_stock = 'En stock';
$out_of_stock_notify = 'Notifícame';
$out_of_stock_notify_2 = 'Visítanos @';
$out_of_stock = 'Agotado';
$add_to_basket = 'Añadir al carrito';
$h1_cart_name = 'Carrito de compra';
$h2_cart_suggestions = 'Sugerencias';
$h2_cart_sample_product = 'Muestras';
$tr_product = 'Producto';
$tr_price = 'Precio';
$tr_quantity = 'Cantidad';
$tr_total = 'Total';
$total_subtotal = 'Subtotal';
$total_note = '(los gastos de envío se calculan durante el pago)';
$total_vat = 'IVA';
$total_shipping = 'Envío';
$total_shipping_note = '(envío incluido)';
$total_discount = 'Descuento';
$total_total = 'Total';
$total_total_note = 'IVA incluido';
$btn_emptycart = 'vaciar';
$btn_update = 'Actualizar';
$btn_checkout = 'Finalizar compra';
$navigation_back_to_store = 'volver a la colección';
$cart_message_empty = 'No tienes productos en tu carrito de compra';
$error_account_name = 'La cuenta ya existe.';
$error_account_password_rules = 'La contraseña debe tener entre 5 y 20 caracteres.';
$error_account_password_match = 'Las contraseñas no coinciden.';
$error_account = 'Se requiere crear una cuenta.';
$h1_checkout = 'Finalizar compra';
$account_available = '¿Ya tienes una cuenta?';
$account_log_in = 'Iniciar sesión';
$account_create = 'Crear cuenta';
$account_create_optional = '(opcional)';
$account_create_email = 'Correo electrónico';
$account_create_password = 'Contraseña';
$account_create_password_confirm = 'Confirmar contraseña';
$h2_Shipping_details = 'Detalles de envío';
$h3_shipping_method = 'Método de envío';
$shipping_first_name = 'Nombre';
$shipping_last_name = 'Apellido';
$shipping_address = 'Dirección';
$shipping_city = 'Ciudad';
$shipping_state = 'Región/Estado';
$shipping_zip = 'Código postal';
$shipping_country = 'País';
$shipping_phone = 'Teléfono';
$payment_method = 'Método de pago';
$payment_method_1 = 'Débito (clientes NL/BE)';
$payment_method_2 = 'Pago contra entrega';
$h2_shoppingcart = 'Carrito de compra';
$discount_label = 'Código de descuento';
$discount_message = '¡Código de descuento aplicado!';
$discount_error_1 = '¡Código de descuento incorrecto!';
$discount_error_2 = '¡Código de descuento caducado!';
$order_consent_1 = 'Me gustaría recibir comunicaciones por correo electrónico sobre noticias, productos y servicios de MorvalWatches';
$order_consent_2 = 'Estoy de acuerdo con';
$order_consent_3 = 'Términos y condiciones';
$btn_place_order = 'Realizar pedido';
$h1_order_succes_message = 'Tu pedido ha sido realizado';
$order_succes_message = '¡Gracias por realizar tu pedido con nosotros! Te contactaremos por correo electrónico con los detalles de tu pedido.';
$error_myaccount = '¡Correo electrónico/contraseña incorrectos!';
$h1_login = 'Iniciar sesión';
$h1_register = 'Registrarse';
$h1_myaccount = 'Mi cuenta';
$h2_menu = 'Menú';
$menu_orders = 'Pedidos';
$menu_downloads = 'Descargas';
$h2_myorders = 'Mis pedidos';
$myorders_message = 'No tienes pedidos';
$myorders_order = 'Pedido';
$myorders_date = 'Fecha';
$myorders_status = 'Estado';
$myorders_shipping = 'Envío';
$myorders_total = 'Total';
$h2_mydownloads = 'Mis descargas';
$mydownloads_message = 'No tienes descargas';
$mydownloads_product = 'Producto';
$h2_settings = 'Configuración';
$settings_email = 'Correo electrónico';
$settings_new_password = 'Nueva contraseña';
$btn_settings_save = 'Guardar';
$age_consent_h4 = 'Comprobemos tu edad';
$age_consent_text = 'Para visitar MorvalWatches debes tener 18 años o más.';
$age_consent_btn_allow = 'Aceptar';
$age_consent_btn_deny = 'Rechazar';
$maintenanceMode_h4 = 'La tienda web está en mantenimiento';
$maintenanceMode_text = 'Nuestra tienda web está en mantenimiento. Esperamos verte pronto de nuevo';
$maintenanceMode_btn = 'OK';
$subject_order_notification = 'MorvalWatches - ¡Has recibido un nuevo pedido!';
$subject_new_order = 'MorvalWatches - Detalles del pedido';
$subject_out_of_stock = 'MorvalWatches - Agotado';
$home_text = 'Inicio';
$products_text = 'Colección';
$about_text = 'Sobre nosotros';
$myaccount_text = 'Cuenta';
$social_punch_line = 'Conéctate con Morval a través de nuestros canales de redes sociales';
$privacy_text = 'Privacidad';
$terms_text = 'Términos y condiciones';
$faq_text = 'Preguntas frecuentes';
$order_email_title = 'MorvalWatches - Pedido';
$order_email_message_1 = 'Gracias por tu pedido';
$order_email_message_2 = 'Tu pedido ha sido recibido y está siendo procesado. Los detalles de tu pedido se encuentran a continuación.';
$order_email_information = 'Tus detalles';
$h2_about_1 = 'Sobre Morval';
$about_header_1 = 'Sobre nosotros';
$about_1_p = 'Morval Watches fue fundada en 2023 por Ralph van Wezel. Ralph es farmacéutico hospitalario y tiene fascinación por la tecnología. En su trabajo se esfuerza por hacer disponibles medicamentos que marquen la diferencia para el paciente. Producir un medicamento requiere conocimiento, precisión, exactitud, técnica, calidad y artesanía. Aquí radica la similitud con la fabricación de un reloj automático de alta calidad. Ralph se ha fijado el objetivo de desarrollar un reloj que pueda competir con las marcas reconocidas, pero que se venda a un precio aceptable.';
$about_header_2 = 'Sobre nuestros relojes';
$about_2_p = 'Un reloj Morval se inspira en los modelos vintage y el diseño minimalista de los relojes escandinavos. Gracias a las variaciones de color de la esfera y las correas, un reloj Morval se puede usar en cualquier ocasión, tanto deportivo como de vestir. Los relojes Morval cumplen con los más altos estándares de calidad y pueden competir con las reconocidas marcas suizas. Las piezas son suministradas por fabricantes de renombre de Europa y el extranjero. Un Morval incorpora un calibre suizo (STP), reconocido por su calidad. El ensamblaje se realiza en Ámsterdam por relojeros reconocidos y cada reloj se somete a un exhaustivo control de calidad para garantizar su funcionalidad y estética. El reloj se ajusta y prueba manualmente para minimizar las desviaciones. ¡Morval ofrece una excelente relación calidad-precio! Al comprar un reloj Morval, tiene la garantía de un reloj atemporal que durará décadas. Se ha prestado especial atención a los detalles, como la caja cepillada de acero inoxidable 316, la superluminova en las agujas, el cristal antirreflejos y la correa de cuero infinitamente ajustable. Esto se traduce en la lujosa apariencia de la marca. ¡Con un reloj Morval tendrás un reloj único, robusto, elegante y atemporal que durará generaciones!';
$about_header_3 = 'Acerca de Morval';
$about_morval_text = 'Lea más sobre la historia de Morval';
$h2_about_morval_1 = 'La historia de Morval';
$h2_about_morval_2 = '';
$about_morval_header_1 = '';
$about_morval_header_2 = '';
$about_morval_header_3 = '';
$about_morval_2_p = 'Tras la limpieza de los escombros, esta gran plaza vacía quedó como una herida en el corazón de sus habitantes. Tres años después, el municipio construyó un pequeño campanario donde se colgaron las tres campanas que se bajaron para la demolición. Patrocinadas por los residentes de la década de 1930, siguen vivas y aún tocan la campana para conmemorar cualquier acontecimiento, ya sea feliz o desafortunado, como lo hacíamos nosotros antaño.';
$about_morval_3_p = 'Tras la limpieza de los escombros, esta gran plaza vacía quedó como una herida en el corazón de sus habitantes. Tres años después, el municipio construyó un pequeño campanario donde se colgaron las tres campanas que se bajaron para la demolición. Patrocinadas por los residentes de la década de 1930, siguen vivas y aún tocan la campana para conmemorar cualquier acontecimiento, feliz o desafortunado, como lo hacíamos nosotros antaño. Gracias a ellos, Morval no olvida su campanario desaparecido.';
$invoice_morval_subject = 'Relojes Morval - factura';
$place_order_header = 'Realizar pedido';
$checkout_header = 'Verificar';
$tax_text = 'TINA';
$h2_cart_samples = 'Muestras';
$products_filters_h2 = 'Filtros';
$btn_filter = 'Filtrar';
$sort = 'Clasificar';
$order_number_text = 'Orden';
$order_date_text = 'Fecha';
$tr_options = 'Opciones';
$order_invoice_text = 'Factura';
$invoice_payment_paid_text = 'El importe total de esta factura está pagado';
$highlight_1 = 'Recopilación';
$highlight_2 = 'Recopilación';
$home_timeless = 'Eterno';
$home_timeless_text = '¡Los relojes Morval son relojes únicos, robustos, elegantes y atemporales que durarán generaciones!';
$shop_action = 'Compra ahora';
$home_quality = 'Calidad';
$home_quality_text = 'Los relojes Morval cumplen con los más altos estándares de calidad y pueden competir con las reconocidas marcas suizas. Las piezas son suministradas por fabricantes de renombre de Europa y el extranjero. Un Morval incorpora un calibre de fabricación suiza (STP), reconocido por su fiabilidad.';
$home_price = 'Precio';
$home_price_text = 'Morval representa una excelente relación calidad-precio.';
$shopping_cart_header = 'Carro de la compra';
$about_3_p = 'Morval toma su nombre del apellido de uno de los abuelos de Ralph. El logotipo está inspirado en el monumento de la ciudad de Morval, en el norte de Francia, construido con los restos de una iglesia y las tres campanas de la torre.';
$newuser_credential_text_1 = 'Su cuenta ha sido creada con nombre de usuario';
$newuser_credential_text_2 = 'Por favor haga clic en el botón de abajo para completar su registro.';
$verify_account = 'Verificar cuenta';
$newuser_signature = ' Atentamente,';
$newuser_signature_name = 'Relojes Morval';
$changeuser_credential_text_1 = 'Haga clic en el botón a continuación para restablecer la contraseña de su cuenta.';
$changeuser_signature = ' Atentamente,';
$changeuser_signature_name = 'Relojes Morval';
$bracelet_dark = 'Negro';
$bracelet_blue = 'Azul oscuro';
$bracelet_dark_brown = 'Marrón oscuro';
$bracelet_light_brown = 'Marrón claro';
$bracelet_steel = 'Acero';
$MWTH1NB_description = '<p>El Thomas-I irradia elegancia y sofisticación. Dimensiones clásicas combinadas con detalles sutiles en la esfera hacen de este un reloj automático especial para cualquier ocasión.</p><h3><b>Especificaciones</b></h3><ul><li>Tamaño de la caja: 39 mm x 10,5 mm.</li><li>Calibre: STP1-11 con 26 rubíes</li><li>Reserva de marcha: 40 h</li><li>Isocronismo: &lt; 10 seg./día</li><li>Bisel: Acero inoxidable pulido (316L)</li><li>Resistente al agua: 50 metros (5 ATM)</li><li>Esfera: Efecto rayo de sol</li><li>Fecha: Números arábigos (día)</li><li>Lumen: Superluminova (Azul)</li><li>Cristal: Zafiro con recubrimiento antirreflectante</li><li>Tapa trasera: Atornillada, acero inoxidable cepillado con cristal de zafiro</li><li>Brazalete (acero): Acero inoxidable 316L cepillado y pulido</li><li>Brazalete (cuero): Cuero de becerro italiano hecho a mano</li><li>Cierre: Mecanismo plegable para máxima comodidad</li><li>Embalaje: Caja azul con certificado y manual.</li></ul>';
$MWTH2NB_description = '<p>El Thomas-II ofrece una vista del corazón palpitante del reloj suizo. Representa la precisión y perfección con la que se muestra el tiempo.</p><h3><b>Especificaciones</b></h3><ul><li>Tamaño de la caja: 39 mm x 10,5 mm.</li><li>Calibre: STP1-11 con 26 rubíes</li><li>Reserva de marcha: 40 h</li><li>Isocronismo: &lt; 10 seg./día</li><li>Bisel: Acero inoxidable cepillado (316L)</li><li>Resistente al agua: 50 metros (5 ATM)</li><li>Esfera: Efecto rayo de sol</li><li>Lumen: Superluminova (Azul)</li><li>Cristal: Zafiro con recubrimiento antirreflectante</li><li>Tapa trasera: Atornillada, acero inoxidable cepillado con cristal de zafiro</li><li>Brazalete (acero): Acero inoxidable 316L cepillado y pulido</li><li>Brazalete (cuero): Cuero de becerro italiano hecho a mano</li><li>Cierre: Mecanismo plegable para máxima comodidad</li><li>Embalaje: Caja azul con certificado y manual.</li></ul>';
$MWTH2IB_description = '<p>El Thomas-II ofrece una vista del corazón palpitante del reloj suizo. Representa la precisión y perfección con la que se muestra el tiempo.</p><h3><b>Especificaciones</b></h3><ul><li>Tamaño de la caja: 39 mm x 10,5 mm.</li><li>Calibre: STP1-11 con 26 rubíes</li><li>Reserva de marcha: 40 h</li><li>Isocronismo: &lt; 10 seg./día</li><li>Bisel: Acero inoxidable cepillado (316L)</li><li>Resistente al agua: 50 metros (5 ATM)</li><li>Esfera: Efecto rayo de sol</li><li>Lumen: Superluminova (Azul)</li><li>Cristal: Zafiro con recubrimiento antirreflectante</li><li>Tapa trasera: Atornillada, acero inoxidable cepillado con cristal de zafiro</li><li>Brazalete (acero): Acero inoxidable 316L cepillado y pulido</li><li>Brazalete (cuero): Cuero de becerro italiano hecho a mano</li><li>Cierre: Mecanismo plegable para máxima comodidad</li><li>Embalaje: Caja azul con certificado y manual.</li></ul>';
$MWTH2RG_description = '<p>El Thomas-II ofrece una vista del corazón palpitante del reloj suizo. Representa la precisión y perfección con la que se muestra el tiempo.</p><h3><b>Especificaciones</b></h3><ul><li>Tamaño de la caja: 39 mm x 10,5 mm.</li><li>Calibre: STP1-11 con 26 rubíes</li><li>Reserva de marcha: 40 h</li><li>Isocronismo: &lt; 10 seg./día</li><li>Bisel: Acero inoxidable cepillado (316L)</li><li>Resistente al agua: 50 metros (5 ATM)</li><li>Esfera: Efecto rayo de sol</li><li>Lumen: Superluminova (Azul)</li><li>Cristal: Zafiro con recubrimiento antirreflectante</li><li>Tapa trasera: Atornillada, acero inoxidable cepillado con cristal de zafiro</li><li>Brazalete (acero): Acero inoxidable 316L cepillado y pulido</li><li>Brazalete (cuero): Cuero de becerro italiano hecho a mano</li><li>Cierre: Mecanismo plegable para máxima comodidad</li><li>Embalaje: Caja azul con certificado y manual.</li></ul>';
$MWTH2DG_description = '<p>El Thomas-II ofrece una vista del corazón palpitante del reloj suizo. Representa la precisión y perfección con la que se muestra el tiempo.</p><h3><b>Especificaciones</b></h3><ul><li>Tamaño de la caja: 39 mm x 10,5 mm.</li><li>Calibre: STP1-11 con 26 rubíes</li><li>Reserva de marcha: 40 h</li><li>Isocronismo: &lt; 10 seg./día</li><li>Bisel: Acero inoxidable cepillado (316L)</li><li>Resistente al agua: 50 metros (5 ATM)</li><li>Esfera: Efecto rayo de sol</li><li>Lumen: Superluminova (Azul)</li><li>Cristal: Zafiro con recubrimiento antirreflectante</li><li>Tapa trasera: Atornillada, acero inoxidable cepillado con cristal de zafiro</li><li>Brazalete (acero): Acero inoxidable 316L cepillado y pulido</li><li>Brazalete (cuero): Cuero de becerro italiano hecho a mano</li><li>Cierre: Mecanismo plegable para máxima comodidad</li><li>Embalaje: Caja azul con certificado y manual.</li></ul>';
$MWTH2G_description = '<p>El Thomas-II ofrece una vista del corazón palpitante del reloj suizo. Representa la precisión y perfección con la que se muestra el tiempo.</p><h3><b>Especificaciones</b></h3><ul><li>Tamaño de la caja: 39 mm x 10,5 mm.</li><li>Calibre: STP1-11 con 26 rubíes</li><li>Reserva de marcha: 40 h</li><li>Isocronismo: &lt; 10 seg./día</li><li>Bisel: Acero inoxidable cepillado (316L)</li><li>Resistente al agua: 50 metros (5 ATM)</li><li>Esfera: Efecto rayo de sol</li><li>Lumen: Superluminova (Azul)</li><li>Cristal: Zafiro con recubrimiento antirreflectante</li><li>Tapa trasera: Atornillada, acero inoxidable cepillado con cristal de zafiro</li><li>Brazalete (acero): Acero inoxidable 316L cepillado y pulido</li><li>Brazalete (cuero): Cuero de becerro italiano hecho a mano</li><li>Cierre: Mecanismo plegable para máxima comodidad</li><li>Embalaje: Caja azul con certificado y manual.</li></ul>';
$MWABRB1_description = 'Pulsera de piel de becerro italiana hecha a mano';
$MWABRDB1_description = 'Pulsera de piel de becerro italiana hecha a mano';
$MWABRLB1_description = 'Pulsera de piel de becerro italiana hecha a mano';
$MWABRBL1_description = 'Pulsera de piel de becerro italiana hecha a mano';
$MWTH1IB_description = '<p>El Thomas-I irradia elegancia y sofisticación. Dimensiones clásicas combinadas con detalles sutiles en la esfera hacen de este un reloj automático especial para cualquier ocasión.</p><h3><b>Especificaciones</b></h3><ul><li>Tamaño de la caja: 39 mm x 10,5 mm.</li><li>Calibre: STP1-11 con 26 rubíes</li><li>Reserva de marcha: 40 h</li><li>Isocronismo: &lt; 10 seg./día</li><li>Bisel: Acero inoxidable pulido (316L)</li><li>Resistente al agua: 50 metros (5 ATM)</li><li>Esfera: Efecto rayo de sol</li><li>Fecha: Números arábigos (día)</li><li>Lumen: Superluminova (Azul)</li><li>Cristal: Zafiro con recubrimiento antirreflectante</li><li>Tapa trasera: Atornillada, acero inoxidable cepillado con cristal de zafiro</li><li>Brazalete (acero): Acero inoxidable 316L cepillado y pulido</li><li>Brazalete (cuero): Cuero de becerro italiano hecho a mano</li><li>Cierre: Mecanismo plegable para máxima comodidad</li><li>Embalaje: Caja azul con certificado y manual.</li></ul>';
$MWTH1RG_description = '<p>El Thomas-I irradia elegancia y sofisticación. Dimensiones clásicas combinadas con detalles sutiles en la esfera hacen de este un reloj automático especial para cualquier ocasión.</p><h3><b>Especificaciones</b></h3><ul><li>Tamaño de la caja: 39 mm x 10,5 mm.</li><li>Calibre: STP1-11 con 26 rubíes</li><li>Reserva de marcha: 40 h</li><li>Isocronismo: &lt; 10 seg./día</li><li>Bisel: Acero inoxidable pulido (316L)</li><li>Resistente al agua: 50 metros (5 ATM)</li><li>Esfera: Efecto rayo de sol</li><li>Fecha: Números arábigos (día)</li><li>Lumen: Superluminova (Azul)</li><li>Cristal: Zafiro con recubrimiento antirreflectante</li><li>Tapa trasera: Atornillada, acero inoxidable cepillado con cristal de zafiro</li><li>Brazalete (acero): Acero inoxidable 316L cepillado y pulido</li><li>Brazalete (cuero): Cuero de becerro italiano hecho a mano</li><li>Cierre: Mecanismo plegable para máxima comodidad</li><li>Embalaje: Caja azul con certificado y manual.</li></ul>';
$MWTH1DG_description = '<p>El Thomas-I irradia elegancia y sofisticación. Dimensiones clásicas combinadas con detalles sutiles en la esfera hacen de este un reloj automático especial para cualquier ocasión.</p><h3><b>Especificaciones</b></h3><ul><li>Tamaño de la caja: 39 mm x 10,5 mm.</li><li>Calibre: STP1-11 con 26 rubíes</li><li>Reserva de marcha: 40 h</li><li>Isocronismo: &lt; 10 seg./día</li><li>Bisel: Acero inoxidable pulido (316L)</li><li>Resistente al agua: 50 metros (5 ATM)</li><li>Esfera: Efecto rayo de sol</li><li>Fecha: Números arábigos (día)</li><li>Lumen: Superluminova (Azul)</li><li>Cristal: Zafiro con recubrimiento antirreflectante</li><li>Tapa trasera: Atornillada, acero inoxidable cepillado con cristal de zafiro</li><li>Brazalete (acero): Acero inoxidable 316L cepillado y pulido</li><li>Brazalete (cuero): Cuero de becerro italiano hecho a mano</li><li>Cierre: Mecanismo plegable para máxima comodidad</li><li>Embalaje: Caja azul con certificado y manual.</li></ul>';
$MWTH1G_description = '<p>El Thomas-I irradia elegancia y sofisticación. Dimensiones clásicas combinadas con detalles sutiles en la esfera hacen de este un reloj automático especial para cualquier ocasión.</p><h3><b>Especificaciones</b></h3><ul><li>Tamaño de la caja: 39 mm x 10,5 mm.</li><li>Calibre: STP1-11 con 26 rubíes</li><li>Reserva de marcha: 40 h</li><li>Isocronismo: &lt; 10 seg./día</li><li>Bisel: Acero inoxidable pulido (316L)</li><li>Resistente al agua: 50 metros (5 ATM)</li><li>Esfera: Efecto rayo de sol</li><li>Fecha: Números arábigos (día)</li><li>Lumen: Superluminova (Azul)</li><li>Cristal: Zafiro con recubrimiento antirreflectante</li><li>Tapa trasera: Atornillada, acero inoxidable cepillado con cristal de zafiro</li><li>Brazalete (acero): Acero inoxidable 316L cepillado y pulido</li><li>Brazalete (cuero): Cuero de becerro italiano hecho a mano</li><li>Cierre: Mecanismo plegable para máxima comodidad</li><li>Embalaje: Caja azul con certificado y manual.</li></ul>';
$payment_status_0 = 'Abierto';
$payment_status_1 = 'Pagado';
$payment_status_101 = 'Pendiente';
$payment_status_102 = 'Fallido';
$payment_status_103 = 'Venció';
$payment_status_999 = 'Cancelado';
$payment_method_3 = 'Débito/Crédito';
$ad_watch_1 = 'Diseño holandés y artesanía suiza';
$ad_watch_2 = '¡Relojes atemporales que durarán generaciones!';
$ad_watch_btn = 'leer más';
$newsletter_h2 = 'Suscríbete al boletín informativo';
$newsletter_p = 'Manténgase conectado con nuestras últimas actualizaciones, consejos y ofertas exclusivas, directamente en su bandeja de entrada.';
$newsletter_confirm = 'He leído y estoy de acuerdo con la política de privacidad.';
$newsletter_submit = 'entregar';
$header_manufacturing = 'Calidad suiza y fabricación holandesa';
$header_shipping = 'Envío gratuito en todos nuestros relojes.';
$header_delivery = 'Servicio y entrega rápidos';
$header_rating = 'Calificación del cliente 4.7/5.0';
?>

View File

@@ -1,209 +0,0 @@
<?php
$h2_brand_name_1 = 'MorvalWatches';
$h2_brand_name_2 = 'une marque avec une histoire';
$h2_brand_visit = 'Visitez notre collection';
$h2_brand_wow = 'Morval réunit une combinaison unique de design minimaliste, qualité suisse et fabrication néerlandaise.Nous vous offrons une montre à porter en toute occasion.';
$h1_content_top = 'Notre collection de montres';
$product_count_1 = 'Produit';
$product_count_2 = 's';
$main_filter_category = 'Catégorie';
$main_category = 'Tous';
$main_filter_sort = 'Trier';
$sort1 = 'A-Z';
$sort2 = 'Z-A';
$sort3 = 'Plus récents';
$sort4 = 'Plus anciens';
$sort5 = 'Prix décroissant';
$sort6 = 'Prix croissant';
$free_delivery = 'livraison gratuite';
$non_free_delivery = 'livraison gratuite à partir de';
$breadcrum_products = 'Collection';
$product_quantity = 'Quantité';
$product_on_stock = 'En stock';
$out_of_stock_notify = 'Prévenez-moi';
$out_of_stock_notify_2 = 'Visitez-nous @';
$out_of_stock = 'En rupture de stock';
$add_to_basket = 'Ajouter au panier';
$h1_cart_name = 'Panier';
$h2_cart_suggestions = 'Suggestions';
$h2_cart_sample_product = 'Échantillons';
$tr_product = 'Produit';
$tr_price = 'Prix';
$tr_quantity = 'Quantité';
$tr_total = 'Total';
$total_subtotal = 'Sous-total';
$total_note = '(les frais d\'expédition sont calculés lors du paiement)';
$total_vat = 'TVA';
$total_shipping = 'Expédition';
$total_shipping_note = '(expédition incluse)';
$total_discount = 'Remise';
$total_total = 'Total';
$total_total_note = 'TVA incluse';
$btn_emptycart = 'vider';
$btn_update = 'Mettre à jour';
$btn_checkout = 'Paiement';
$navigation_back_to_store = 'retour à la collection';
$cart_message_empty = 'Vous n\'avez pas de produits dans votre panier';
$error_account_name = 'Le compte existe déjà.';
$error_account_password_rules = 'Le mot de passe doit comporter entre 5 et 20 caractères.';
$error_account_password_match = 'Les mots de passe ne correspondent pas.';
$error_account = 'Création de compte requise.';
$h1_checkout = 'Paiement';
$account_available = 'Vous avez déjà un compte?';
$account_log_in = 'Se connecter';
$account_create = 'Créer un compte';
$account_create_optional = '(facultatif)';
$account_create_email = 'Email';
$account_create_password = 'Mot de passe';
$account_create_password_confirm = 'Confirmer le mot de passe';
$h2_Shipping_details = 'Détails de livraison';
$h3_shipping_method = 'Méthode d\'expédition';
$shipping_first_name = 'Prénom';
$shipping_last_name = 'Nom';
$shipping_address = 'Adresse';
$shipping_city = 'Ville';
$shipping_state = 'Région/État';
$shipping_zip = 'Code postal';
$shipping_country = 'Pays';
$shipping_phone = 'Téléphone';
$payment_method = 'Méthode de paiement';
$payment_method_1 = 'Débit (clients NL/BE)';
$payment_method_2 = 'Paiement à la livraison';
$h2_shoppingcart = 'Panier';
$discount_label = 'Code de réduction';
$discount_message = 'Code de réduction appliqué!';
$discount_error_1 = 'Code de réduction incorrect!';
$discount_error_2 = 'Code de réduction expiré!';
$order_consent_1 = 'Je souhaite recevoir des communications par email concernant les actualités, produits et services de MorvalWatches';
$order_consent_2 = 'J\'accepte';
$order_consent_3 = 'Conditions générales';
$btn_place_order = 'Commander';
$h1_order_succes_message = 'Votre commande a été passée';
$order_succes_message = 'Merci d\'avoir commandé chez nous! Nous vous contacterons par email avec les détails de votre commande.';
$error_myaccount = 'Email/Mot de passe incorrect!';
$h1_login = 'Connexion';
$h1_register = 'S\'inscrire';
$h1_myaccount = 'Mon compte';
$h2_menu = 'Menu';
$menu_orders = 'Commandes';
$menu_downloads = 'Téléchargements';
$h2_myorders = 'Mes commandes';
$myorders_message = 'Vous n\'avez pas de commandes';
$myorders_order = 'Commande';
$myorders_date = 'Date';
$myorders_status = 'Statut';
$myorders_shipping = 'Expédition';
$myorders_total = 'Total';
$h2_mydownloads = 'Mes téléchargements';
$mydownloads_message = 'Vous n\'avez pas de téléchargements';
$mydownloads_product = 'Produit';
$h2_settings = 'Paramètres';
$settings_email = 'Email';
$settings_new_password = 'Nouveau mot de passe';
$btn_settings_save = 'Enregistrer';
$age_consent_h4 = 'Vérifions votre âge';
$age_consent_text = 'Pour visiter MorvalWatches, vous devez avoir 18 ans ou plus.';
$age_consent_btn_allow = 'J\'accepte';
$age_consent_btn_deny = 'Je refuse';
$maintenanceMode_h4 = 'La boutique en ligne est en maintenance';
$maintenanceMode_text = 'Notre boutique en ligne est en maintenance. Nous espérons vous revoir bientôt';
$maintenanceMode_btn = 'OK';
$subject_order_notification = 'MorvalWatches - Vous avez reçu une nouvelle commande!';
$subject_new_order = 'MorvalWatches - Détails de la commande';
$subject_out_of_stock = 'MorvalWatches - Rupture de stock';
$home_text = 'Accueil';
$products_text = 'Collection';
$about_text = 'À propos';
$myaccount_text = 'Compte';
$social_punch_line = 'Connectez-vous avec Morval via nos réseaux sociaux';
$privacy_text = 'Confidentialité';
$terms_text = 'Conditions générales';
$faq_text = 'Questions fréquemment posées';
$order_email_title = 'MorvalWatches - Commande';
$order_email_message_1 = 'Merci pour votre commande';
$order_email_message_2 = 'Votre commande a été reçue et est en cours de traitement. Les détails de votre commande sont ci-dessous.';
$order_email_information = 'Vos détails';
$h2_about_1 = 'À propos de Morval';
$about_header_1 = 'À propos';
$about_1_p = 'Morval Watches a été fondée en 2023 par Ralph van Wezel. Ralph est pharmacien hospitalier et a une fascination pour la technologie. Dans son travail, il s\'efforce de rendre disponibles des médicaments qui font une différence pour le patient. La production d\'un médicament nécessite des connaissances, de la précision, de l\'exactitude, de la technique, de la qualité et du savoir-faire. C\'est là que réside la similitude avec la fabrication d\'une montre automatique de haute qualité. Ralph s\'est fixé comme objectif de développer une montre capable de rivaliser avec les marques renommées, mais vendue à un prix acceptable.';
$about_header_2 = 'À propos de nos montres';
$about_2_p = 'Une montre Morval s\'inspire des modèles vintage et du design minimaliste des montres scandinaves. Grâce aux variations de couleurs du cadran et du bracelet, une montre Morval peut être portée en toute occasion, aussi bien pour le sport que pour une tenue habillée. Les montres Morval répondent aux plus hautes exigences de qualité et rivalisent avec les grandes marques suisses. Les composants proviennent de fabricants renommés d\'Europe et d\'ailleurs. Une Morval est équipée d\'un calibre de fabrication suisse (STP), reconnu pour sa fiabilité. L\'assemblage est réalisé à Amsterdam par des horlogers reconnus et chaque montre est soumise à des contrôles qualité rigoureux garantissant sa fonctionnalité et son esthétique. La montre est réglée et testée manuellement afin de minimiser les écarts de couleur. Morval est synonyme d\'un excellent rapport qualité-prix ! En achetant une montre Morval, vous avez l\'assurance d\'une montre intemporelle qui durera des décennies. Une attention particulière a été portée aux détails, tels qu\'un boîtier brossé en acier inoxydable 316, des aiguilles Superluminova, un verre antireflet et un bracelet en cuir réglable en continu. Cela reflète l\'allure luxueuse de la marque. Avec une montre Morval, vous disposez d\'un garde-temps unique, robuste, élégant et intemporel qui durera des générations !';
$about_header_3 = 'À propos de Morval';
$about_morval_text = 'En savoir plus sur l\'histoire de Morval';
$h2_about_morval_1 = 'L\'histoire de Morval';
$h2_about_morval_2 = '';
$about_morval_header_1 = '';
$about_morval_header_2 = '';
$about_morval_header_3 = '';
$about_morval_2_p = 'Une fois les décombres dégagés, cette grande place vide demeurait comme une blessure au cœur des habitants. Trois ans plus tard, la municipalité construisit un petit campanile où furent accrochées les trois cloches descendues pour la démolition. Parrainées par les habitants des années 1930, elles sont toujours vivantes et sonnent encore la cloche pour commémorer chaque événement heureux ou malheureux, comme nous le faisions autrefois.';
$about_morval_3_p = 'Une fois les décombres dégagés, cette grande place vide demeura comme une plaie dans le cœur des habitants. Trois ans plus tard, la municipalité construisit un petit campanile où furent accrochées les trois cloches descendues pour la démolition. Parrainées par les habitants des années 1930, elles sont toujours vivantes et sonnent encore la cloche pour commémorer chaque événement heureux ou malheureux, comme nous le faisions autrefois. Grâce à eux, Morval n\'oublie pas son clocher disparu.';
$invoice_morval_subject = 'Montres Morval - facture';
$place_order_header = 'Passer commande';
$checkout_header = 'Vérifier';
$tax_text = 'T.V.A.';
$h2_cart_samples = 'Échantillons';
$products_filters_h2 = 'Filtres';
$btn_filter = 'Filtre';
$sort = 'Trier';
$order_number_text = 'Commande';
$order_date_text = 'Date';
$tr_options = 'Options';
$order_invoice_text = 'Facture';
$invoice_payment_paid_text = 'Le montant total de cette facture est payé';
$highlight_1 = 'Collection';
$highlight_2 = 'Collection';
$home_timeless = 'Intemporel';
$home_timeless_text = 'Les montres Morval sont des garde-temps uniques, robustes, élégants et intemporels qui dureront des générations !';
$shop_action = 'achetez maintenant';
$home_quality = 'Qualité';
$home_quality_text = 'Les montres Morval répondent aux plus hautes exigences de qualité et rivalisent avec les grandes marques suisses. Les composants proviennent de fabricants renommés d\'Europe et d\'ailleurs. Une Morval est équipée d\'un calibre suisse (STP), reconnu pour sa fiabilité.';
$home_price = 'Prix';
$home_price_text = 'Morval est synonyme d\'un excellent rapport qualité-prix';
$shopping_cart_header = 'Panier';
$about_3_p = 'Morval tire son nom du nom de famille de l\'un des grands-parents de Ralph. Le logo s\'inspire du monument de la ville de Morval, dans le nord de la France, construit à partir des vestiges d\'une église et des trois cloches de son clocher.';
$newuser_credential_text_1 = 'Votre compte a été créé avec le nom d\'utilisateur';
$newuser_credential_text_2 = 'Veuillez cliquer sur le bouton ci-dessous pour terminer votre inscription.';
$verify_account = 'Vérifier le compte';
$newuser_signature = ' Cordialement,';
$newuser_signature_name = 'Montres Morval';
$changeuser_credential_text_1 = 'Veuillez cliquer sur le bouton ci-dessous pour réinitialiser le mot de passe de votre compte.';
$changeuser_signature = ' Cordialement,';
$changeuser_signature_name = 'Montres Morval';
$bracelet_dark = 'Noir';
$bracelet_blue = 'Bleu foncé';
$bracelet_dark_brown = 'Brun foncé';
$bracelet_light_brown = 'Marron clair';
$bracelet_steel = 'Acier';
$MWTH1NB_description = '<p>La Thomas-I dégage élégance et sophistication. Des dimensions classiques combinées à des détails subtils sur le cadran en font une montre automatique spéciale à porter en toute occasion.</p><h3><b>Caractéristiques</b></h3><ul><li>Taille du boîtier : 39 mm x 10,5 mm.</li><li>Calibre : STP1-11 avec 26 rubis</li><li>Réserve de marche : 40 h</li><li>Isochronisme : &lt; 10 sec./jour</li><li>Lunette : Acier inoxydable poli (316L)</li><li>Étanchéité : 50 mètres (5 ATM)</li><li>Cadran : Cadran effet rayon de soleil</li><li>Date : Chiffres arabes (jour)</li><li>Luminescence : Superluminova (Bleu)</li><li>Verre : Saphir avec revêtement antireflet</li><li>Fond du boîtier : Vissé, acier inoxydable brossé avec verre saphir</li><li>Bracelet (acier) : Acier inoxydable 316L brossé et poli</li><li>Bracelet (cuir) : Cuir de veau italien fait main</li><li>Boucle : Mécanisme déployant pour un confort optimal</li><li>Emballage : Boîte bleue avec certificat et manuel.</li></ul>';
$MWTH2NB_description = '<p>La Thomas-II offre une vue sur le cœur battant de la montre suisse. Elle incarne la précision et la perfection avec lesquelles lheure est affichée.</p><h3><b>Caractéristiques</b></h3><ul><li>Taille du boîtier : 39 mm x 10,5 mm.</li><li>Calibre : STP1-11 avec 26 rubis</li><li>Réserve de marche : 40 h</li><li>Isochronisme : &lt; 10 sec./jour</li><li>Lunette : Acier inoxydable brossé (316L)</li><li>Étanchéité : 50 mètres (5 ATM)</li><li>Cadran : Cadran effet rayon de soleil</li><li>Luminescence : Superluminova (Bleu)</li><li>Verre : Saphir avec revêtement antireflet</li><li>Fond du boîtier : Vissé, acier inoxydable brossé avec verre saphir</li><li>Bracelet (acier) : Acier inoxydable 316L brossé et poli</li><li>Bracelet (cuir) : Cuir de veau italien fait main</li><li>Boucle : Mécanisme déployant pour un confort optimal</li><li>Emballage : Boîte bleue avec certificat et manuel.</li></ul>';
$MWTH2IB_description = '<p>La Thomas-II offre une vue sur le cœur battant de la montre suisse. Elle incarne la précision et la perfection avec lesquelles lheure est affichée.</p><h3><b>Caractéristiques</b></h3><ul><li>Taille du boîtier : 39 mm x 10,5 mm.</li><li>Calibre : STP1-11 avec 26 rubis</li><li>Réserve de marche : 40 h</li><li>Isochronisme : &lt; 10 sec./jour</li><li>Lunette : Acier inoxydable brossé (316L)</li><li>Étanchéité : 50 mètres (5 ATM)</li><li>Cadran : Cadran effet rayon de soleil</li><li>Luminescence : Superluminova (Bleu)</li><li>Verre : Saphir avec revêtement antireflet</li><li>Fond du boîtier : Vissé, acier inoxydable brossé avec verre saphir</li><li>Bracelet (acier) : Acier inoxydable 316L brossé et poli</li><li>Bracelet (cuir) : Cuir de veau italien fait main</li><li>Boucle : Mécanisme déployant pour un confort optimal</li><li>Emballage : Boîte bleue avec certificat et manuel.</li></ul>';
$MWTH2RG_description = '<p>La Thomas-II offre une vue sur le cœur battant de la montre suisse. Elle incarne la précision et la perfection avec lesquelles lheure est affichée.</p><h3><b>Caractéristiques</b></h3><ul><li>Taille du boîtier : 39 mm x 10,5 mm.</li><li>Calibre : STP1-11 avec 26 rubis</li><li>Réserve de marche : 40 h</li><li>Isochronisme : &lt; 10 sec./jour</li><li>Lunette : Acier inoxydable brossé (316L)</li><li>Étanchéité : 50 mètres (5 ATM)</li><li>Cadran : Cadran effet rayon de soleil</li><li>Luminescence : Superluminova (Bleu)</li><li>Verre : Saphir avec revêtement antireflet</li><li>Fond du boîtier : Vissé, acier inoxydable brossé avec verre saphir</li><li>Bracelet (acier) : Acier inoxydable 316L brossé et poli</li><li>Bracelet (cuir) : Cuir de veau italien fait main</li><li>Boucle : Mécanisme déployant pour un confort optimal</li><li>Emballage : Boîte bleue avec certificat et manuel.</li></ul>';
$MWTH2DG_description = '<p>La Thomas-II offre une vue sur le cœur battant de la montre suisse. Elle incarne la précision et la perfection avec lesquelles lheure est affichée.</p><h3><b>Caractéristiques</b></h3><ul><li>Taille du boîtier : 39 mm x 10,5 mm.</li><li>Calibre : STP1-11 avec 26 rubis</li><li>Réserve de marche : 40 h</li><li>Isochronisme : &lt; 10 sec./jour</li><li>Lunette : Acier inoxydable brossé (316L)</li><li>Étanchéité : 50 mètres (5 ATM)</li><li>Cadran : Cadran effet rayon de soleil</li><li>Luminescence : Superluminova (Bleu)</li><li>Verre : Saphir avec revêtement antireflet</li><li>Fond du boîtier : Vissé, acier inoxydable brossé avec verre saphir</li><li>Bracelet (acier) : Acier inoxydable 316L brossé et poli</li><li>Bracelet (cuir) : Cuir de veau italien fait main</li><li>Boucle : Mécanisme déployant pour un confort optimal</li><li>Emballage : Boîte bleue avec certificat et manuel.</li></ul>';
$MWTH2G_description = '<p>La Thomas-II offre une vue sur le cœur battant de la montre suisse. Elle incarne la précision et la perfection avec lesquelles lheure est affichée.</p><h3><b>Caractéristiques</b></h3><ul><li>Taille du boîtier : 39 mm x 10,5 mm.</li><li>Calibre : STP1-11 avec 26 rubis</li><li>Réserve de marche : 40 h</li><li>Isochronisme : &lt; 10 sec./jour</li><li>Lunette : Acier inoxydable brossé (316L)</li><li>Étanchéité : 50 mètres (5 ATM)</li><li>Cadran : Cadran effet rayon de soleil</li><li>Luminescence : Superluminova (Bleu)</li><li>Verre : Saphir avec revêtement antireflet</li><li>Fond du boîtier : Vissé, acier inoxydable brossé avec verre saphir</li><li>Bracelet (acier) : Acier inoxydable 316L brossé et poli</li><li>Bracelet (cuir) : Cuir de veau italien fait main</li><li>Boucle : Mécanisme déployant pour un confort optimal</li><li>Emballage : Boîte bleue avec certificat et manuel.</li></ul>';
$MWABRB1_description = 'Bracelet en cuir de veau italien fait main';
$MWABRDB1_description = 'Bracelet en cuir de veau italien fait main';
$MWABRLB1_description = 'Bracelet en cuir de veau italien fait main';
$MWABRBL1_description = 'Bracelet en cuir de veau italien fait main';
$MWTH1IB_description = '<p>La Thomas-I dégage élégance et sophistication. Des dimensions classiques combinées à des détails subtils sur le cadran en font une montre automatique spéciale à porter en toute occasion.</p><h3><b>Caractéristiques</b></h3><ul><li>Taille du boîtier : 39 mm x 10,5 mm.</li><li>Calibre : STP1-11 avec 26 rubis</li><li>Réserve de marche : 40 h</li><li>Isochronisme : &lt; 10 sec./jour</li><li>Lunette : Acier inoxydable poli (316L)</li><li>Étanchéité : 50 mètres (5 ATM)</li><li>Cadran : Cadran effet rayon de soleil</li><li>Date : Chiffres arabes (jour)</li><li>Luminescence : Superluminova (Bleu)</li><li>Verre : Saphir avec revêtement antireflet</li><li>Fond du boîtier : Vissé, acier inoxydable brossé avec verre saphir</li><li>Bracelet (acier) : Acier inoxydable 316L brossé et poli</li><li>Bracelet (cuir) : Cuir de veau italien fait main</li><li>Boucle : Mécanisme déployant pour un confort optimal</li><li>Emballage : Boîte bleue avec certificat et manuel.</li></ul>';
$MWTH1RG_description = '<p>La Thomas-I dégage élégance et sophistication. Des dimensions classiques combinées à des détails subtils sur le cadran en font une montre automatique spéciale à porter en toute occasion.</p><h3><b>Caractéristiques</b></h3><ul><li>Taille du boîtier : 39 mm x 10,5 mm.</li><li>Calibre : STP1-11 avec 26 rubis</li><li>Réserve de marche : 40 h</li><li>Isochronisme : &lt; 10 sec./jour</li><li>Lunette : Acier inoxydable poli (316L)</li><li>Étanchéité : 50 mètres (5 ATM)</li><li>Cadran : Cadran effet rayon de soleil</li><li>Date : Chiffres arabes (jour)</li><li>Luminescence : Superluminova (Bleu)</li><li>Verre : Saphir avec revêtement antireflet</li><li>Fond du boîtier : Vissé, acier inoxydable brossé avec verre saphir</li><li>Bracelet (acier) : Acier inoxydable 316L brossé et poli</li><li>Bracelet (cuir) : Cuir de veau italien fait main</li><li>Boucle : Mécanisme déployant pour un confort optimal</li><li>Emballage : Boîte bleue avec certificat et manuel.</li></ul>';
$MWTH1DG_description = '<p>La Thomas-I dégage élégance et sophistication. Des dimensions classiques combinées à des détails subtils sur le cadran en font une montre automatique spéciale à porter en toute occasion.</p><h3><b>Caractéristiques</b></h3><ul><li>Taille du boîtier : 39 mm x 10,5 mm.</li><li>Calibre : STP1-11 avec 26 rubis</li><li>Réserve de marche : 40 h</li><li>Isochronisme : &lt; 10 sec./jour</li><li>Lunette : Acier inoxydable poli (316L)</li><li>Étanchéité : 50 mètres (5 ATM)</li><li>Cadran : Cadran effet rayon de soleil</li><li>Date : Chiffres arabes (jour)</li><li>Luminescence : Superluminova (Bleu)</li><li>Verre : Saphir avec revêtement antireflet</li><li>Fond du boîtier : Vissé, acier inoxydable brossé avec verre saphir</li><li>Bracelet (acier) : Acier inoxydable 316L brossé et poli</li><li>Bracelet (cuir) : Cuir de veau italien fait main</li><li>Boucle : Mécanisme déployant pour un confort optimal</li><li>Emballage : Boîte bleue avec certificat et manuel.</li></ul>';
$MWTH1G_description = '<p>La Thomas-I dégage élégance et sophistication. Des dimensions classiques combinées à des détails subtils sur le cadran en font une montre automatique spéciale à porter en toute occasion.</p><h3><b>Caractéristiques</b></h3><ul><li>Taille du boîtier : 39 mm x 10,5 mm.</li><li>Calibre : STP1-11 avec 26 rubis</li><li>Réserve de marche : 40 h</li><li>Isochronisme : &lt; 10 sec./jour</li><li>Lunette : Acier inoxydable poli (316L)</li><li>Étanchéité : 50 mètres (5 ATM)</li><li>Cadran : Cadran effet rayon de soleil</li><li>Date : Chiffres arabes (jour)</li><li>Luminescence : Superluminova (Bleu)</li><li>Verre : Saphir avec revêtement antireflet</li><li>Fond du boîtier : Vissé, acier inoxydable brossé avec verre saphir</li><li>Bracelet (acier) : Acier inoxydable 316L brossé et poli</li><li>Bracelet (cuir) : Cuir de veau italien fait main</li><li>Boucle : Mécanisme déployant pour un confort optimal</li><li>Emballage : Boîte bleue avec certificat et manuel.</li></ul>';
$payment_status_0 = 'Ouvrir';
$payment_status_1 = 'Payé';
$payment_status_101 = 'En attente';
$payment_status_102 = 'Échoué';
$payment_status_103 = 'Expiré';
$payment_status_999 = 'Annulé';
$payment_method_3 = 'Débit/Crédit';
$ad_watch_1 = 'Design néerlandais et artisanat suisse';
$ad_watch_2 = 'Des montres intemporelles qui dureront des générations !';
$ad_watch_btn = 'En savoir plus';
$newsletter_h2 = 'Inscrivez-vous à la newsletter';
$newsletter_p = 'Restez connecté avec nos dernières mises à jour, conseils et offres exclusives, directement dans votre boîte de réception.';
$newsletter_confirm = 'J\'ai lu et j\'accepte la politique de confidentialité';
$newsletter_submit = 'soumettre';
$header_manufacturing = 'Qualité suisse et fabrication néerlandaise';
$header_shipping = 'Livraison gratuite sur toutes nos montres';
$header_delivery = 'Service et livraison rapides';
$header_rating = 'Note client 4,7/5,0';
?>

View File

@@ -1,2 +0,0 @@
<?php
?>

View File

@@ -1,219 +0,0 @@
<?php
$h2_brand_name_1 = 'MorvalWatches';
$h2_brand_name_2 = 'een merk met een verhaal';
$h2_brand_visit = 'Bezoek onze collectie';
$h2_brand_wow = 'Morval brengt een unieke combinatie samen van minimalistisch design, Zwitserse kwaliteit en Nederlandse productie.Wij bieden u een horloge dat bij elke gelegenheid gedragen kan worden.';
$h1_content_top = 'Onze horlogecollectie';
$product_count_1 = 'Product';
$product_count_2 = 'en';
$main_filter_category = 'Categorie';
$main_category = 'Alle';
$main_filter_sort = 'Sorteren';
$sort1 = 'A-Z';
$sort2 = 'Z-A';
$sort3 = 'Nieuwste';
$sort4 = 'Oudste';
$sort5 = 'Prijs hoog - laag';
$sort6 = 'Prijs laag - hoog';
$free_delivery = 'gratis verzending';
$non_free_delivery = 'gratis verzending vanaf';
$breadcrum_products = 'Collectie';
$product_quantity = 'Aantal';
$product_on_stock = 'Op voorraad';
$out_of_stock_notify = 'Breng me op de hoogte';
$out_of_stock_notify_2 = 'Bezoek ons @';
$out_of_stock = 'Niet op voorraad';
$add_to_basket = 'Toevoegen aan winkelwagen';
$h1_cart_name = 'Winkelwagen';
$h2_cart_suggestions = 'Suggesties';
$h2_cart_sample_product = 'Voorbeelden';
$tr_product = 'Product';
$tr_price = 'Prijs';
$tr_quantity = 'Aantal';
$tr_total = 'Totaal';
$total_subtotal = 'Subtotaal';
$total_note = '(verzendkosten worden berekend tijdens het afrekenen)';
$total_vat = 'BTW';
$total_shipping = 'Verzending';
$total_shipping_note = '(verzending inbegrepen)';
$total_discount = 'Korting';
$total_total = 'Totaal';
$total_total_note = 'BTW inbegrepen';
$btn_emptycart = 'leegmaken';
$btn_update = 'Bijwerken';
$btn_checkout = 'Afrekenen';
$navigation_back_to_store = 'terug naar collectie';
$cart_message_empty = 'U heeft geen producten in uw winkelwagen';
$error_account_name = 'Account bestaat al.';
$error_account_password_rules = 'Wachtwoord moet tussen 5 en 20 tekens lang zijn.';
$error_account_password_match = 'Wachtwoorden komen niet overeen.';
$error_account = 'Account aanmaken vereist.';
$h1_checkout = 'Afrekenen';
$account_available = 'Heeft u al een account?';
$account_log_in = 'Inloggen';
$account_create = 'Account aanmaken';
$account_create_optional = '(optioneel)';
$account_create_email = 'E-mail';
$account_create_password = 'Wachtwoord';
$account_create_password_confirm = 'Bevestig wachtwoord';
$h2_Shipping_details = 'Verzendgegevens';
$h3_shipping_method = 'Verzendmethode';
$shipping_first_name = 'Voornaam';
$shipping_last_name = 'Achternaam';
$shipping_address = 'Adres';
$shipping_city = 'Stad';
$shipping_state = 'Regio/Provincie';
$shipping_zip = 'Postcode';
$shipping_country = 'Land';
$shipping_phone = 'Telefoon';
$payment_method = 'Betaalmethode';
$payment_method_1 = 'Incasso (NL/BE klanten)';
$payment_method_2 = 'Betaling bij levering';
$h2_shoppingcart = 'Winkelwagen';
$discount_label = 'Kortingscode';
$discount_message = 'Kortingscode toegepast!';
$discount_error_1 = 'Onjuiste kortingscode!';
$discount_error_2 = 'Kortingscode verlopen!';
$order_consent_1 = 'Ik wil graag e-mailcommunicatie ontvangen over MorvalWatches nieuws, producten en diensten';
$order_consent_2 = 'Ik ga akkoord met';
$order_consent_3 = 'Algemene voorwaarden';
$btn_place_order = 'Bestellen';
$h1_order_succes_message = 'Uw bestelling is geplaatst';
$order_succes_message = 'Bedankt voor uw bestelling! We nemen contact met u op via e-mail met uw bestelgegevens.';
$error_myaccount = 'Onjuiste e-mail/wachtwoord!';
$h1_login = 'Inloggen';
$h1_register = 'Registreren';
$h1_myaccount = 'Mijn account';
$h2_menu = 'Menu';
$menu_orders = 'Bestellingen';
$menu_downloads = 'Downloads';
$menu_settings = 'Instellingen';
$h2_myorders = 'Mijn bestellingen';
$myorders_message = 'U heeft geen bestellingen';
$myorders_order = 'Bestelling';
$myorders_date = 'Datum';
$myorders_status = 'Status';
$myorders_shipping = 'Verzending';
$myorders_total = 'Totaal';
$h2_mydownloads = 'Mijn downloads';
$mydownloads_message = 'U heeft geen downloads';
$mydownloads_product = 'Product';
$h2_settings = 'Instellingen';
$settings_email = 'E-mail';
$settings_new_password = 'Nieuw wachtwoord';
$btn_settings_save = 'Opslaan';
$age_consent_h4 = 'Laten we uw leeftijd controleren';
$age_consent_text = 'Om MorvalWatches te bezoeken moet u 18 jaar of ouder zijn.';
$age_consent_btn_allow = 'Akkoord';
$age_consent_btn_deny = 'Weigeren';
$maintenanceMode_h4 = 'Webshop is in onderhoud';
$maintenanceMode_text = 'Onze webshop is in onderhoud. We zien u graag snel terug';
$maintenanceMode_btn = 'OK';
$subject_order_notification = 'MorvalWatches - U heeft een nieuwe bestelling ontvangen!';
$subject_new_order = 'MorvalWatches - Bestelgegevens';
$subject_out_of_stock = 'MorvalWatches - Niet op voorraad';
$home_text = 'Home';
$products_text = 'Collectie';
$about_text = 'Over ons';
$myaccount_text = 'Account';
$social_punch_line = 'Verbind met Morval via onze social media kanalen';
$privacy_text = 'Privacy';
$terms_text = 'Algemene voorwaarden';
$faq_text = 'Veelgestelde vragen';
$order_email_title = 'MorvalWatches - Bestelling';
$order_email_message_1 = 'Bedankt voor uw bestelling';
$order_email_message_2 = 'Uw bestelling is ontvangen en wordt momenteel verwerkt. De details van uw bestelling vindt u hieronder.';
$order_email_information = 'Uw gegevens';
$h2_about_1 = 'Over Morval';
$h2_about_2 = '';
$about_header_1 = 'Over ons';
$about_1_p = 'Morval Watches werd in 2023 opgericht door Ralph van Wezel. Ralph is ziekenhuisapotheker en heeft een fascinatie voor technologie. In zijn werk streeft hij ernaar om geneesmiddelen beschikbaar te maken die een verschil maken voor de patiënt. Het produceren van een geneesmiddel vereist kennis, precisie, nauwkeurigheid, techniek, kwaliteit en vakmanschap. Hierin ligt de overeenkomst met de vervaardiging van een hoogwaardige automatische horloge. Ralph heeft zich tot doel gesteld een horloge te ontwikkelen dat kan concurreren met de gerenommeerde merken, maar tegen een acceptabele prijs wordt verkocht.';
$about_header_2 = 'Over onze horloges';
$about_2_p = 'Een Morval horloge is geïnspireerd op de vintage modellen en het minimalistische design van Scandinavische horloges. Door de kleurvariaties van de wijzerplaat en banden kan een Morval horloge bij elke gelegenheid gedragen worden, zowel als sport- als dresshorloge. Morval horloges voldoen aan de hoogste kwaliteitseisen en kunnen wedijveren met de bekende Zwitserse merken. De onderdelen worden geleverd door gerenommeerde fabrikanten uit Europa en daarbuiten. Een Morval bevat een Swiss made kaliber (STP) dat bekend staat om zijn betrouwbare kwaliteit. De assemblage vindt plaats in Amsterdam door erkende horlogemakers en elk horloge ondergaat een uitgebreide kwaliteitscontrole op functionaliteit en esthetiek. Het horloge wordt handmatig afgesteld en getest om de afwijking te minimaliseren. Morval staat voor een uitstekende prijs-kwaliteitverhouding! Wanneer u een Morval horloge koopt, bent u verzekerd van een tijdloos uurwerk dat tientallen jaren meegaat. Er is veel aandacht besteed aan details, zoals een geborstelde kast van roestvrij staal 316, superluminova op de wijzers, ontspiegeld glas en traploos verstelbare leren band. Dit vertaalt zich in de luxe uitstraling van het merk. Met een Morval Horloge heeft u een uniek, robuust, stijlvol en tijdloos horloge dat generaties lang meegaat!';
$about_header_3 = 'Over Morval';
$about_morval_text = 'Lees meer over de geschiedenis van Morval';
$h2_about_morval_1 = 'De geschiedenis van Morval';
$h2_about_morval_2 = '';
$about_morval_header_1 = '';
$about_morval_header_2 = '';
$about_morval_header_3 = '';
$about_morval_1_p = ' Morval, een dorp met 96 inwoners, ligt tussen 4 gemeenten van de Somme als een schiereiland van Pas-de-Calais aan het einde van het kanton Bapaume. Vóór 1914 telde het 220 tot 250 inwoners, maar het werd volledig verwoest tijdens de Slag bij Morval in de Eerste Wereldoorlog (1914-18). De herbouwde kerk was qua stijl, allure en verhoudingen (45 meter hoog, 40 meter lang) een bijna exacte kopie van de vorige. De klokkentoren herbergde 3 prachtige klokken, wat vrij zeldzaam is voor een klein dorp. Het werd ingehuldigd in oktober 1932. Helaas was het geen goede wederopbouw en na de Tweede Wereldoorlog was het noodzakelijk om het dak te repareren, scheuren rond de klokkentoren te dichten, glas-in-loodramen te vervangen, enz. Al snel konden opeenvolgende gemeenten de achteruitgang niet meer aan. Een volledige renovatie zou minstens 1.500.000 frank hebben gekost, terwijl het jaarlijkse budget van de gemeente slechts 120.000 frank bedroeg. In november 1973 stortte tijdens een begrafenis een deel van de kerk in tijdens het offer. Het gebouw was niet langer veilig en werd gesloten voor erediensten. In 1985 besloten de burgemeester, afgevaardigden, raadsleden en bestuurders de kerk te vernietigen. Voor deze zeer trieste operatie werd een bedrag van 66.000 frank gereserveerd, dat werd verlicht door een subsidie verkregen van de algemene raad.';
$about_morval_2_p = 'Toen het puin was geruimd, bleef dit grote lege plein als een wond achter in de harten van de inwoners. Drie jaar later bouwde de gemeente een kleine klokkentoren waar de drie klokken werden opgehangen die voor de sloop waren neergelaten. Gesponsord door inwoners uit de jaren 30, leven ze nog steeds en luiden ze nog steeds de klok om elke gelukkige of ongelukkige gebeurtenis te vieren, zoals wij vroeger deden.';
$about_morval_3_p = 'Toen het puin was geruimd, bleef dit grote lege plein als een wond achter in de harten van de inwoners. Drie jaar later bouwde de gemeente een kleine klokkentoren waar de drie klokken werden opgehangen die voor de sloop waren neergelaten. Gesponsord door inwoners uit de jaren 30, leven ze nog steeds en luiden ze nog steeds de klokken om elke gelukkige of ongelukkige gebeurtenis te vieren, zoals wij dat vroeger deden. Dankzij hen vergeet Morval zijn verdwenen klokkentoren niet.';
$invoice_morval_subject = 'Morval horloges - factuur';
$place_order_header = 'Bestelling plaatsen';
$checkout_header = 'Uitchecken';
$tax_text = 'VAT';
$h2_cart_samples = 'Monsters';
$products_filters_h2 = 'Filters';
$btn_filter = 'Filter';
$sort = 'Soort';
$order_number_text = 'Volgorde';
$order_date_text = 'Datum';
$tr_options = 'Opties';
$order_invoice_text = 'Factuur';
$invoice_payment_paid_text = 'Het totaalbedrag van deze factuur wordt betaald';
$highlight_1 = 'Verzameling';
$highlight_2 = 'Verzameling';
$home_timeless = 'Tijdloos';
$home_timeless_text = 'Morval Horloges zijn unieke, robuuste, stijlvolle en tijdloze horloges die generaties lang meegaan!';
$shop_action = 'nu winkelen';
$home_quality = 'Kwaliteit';
$home_quality_text = 'Morval horloges voldoen aan de hoogste kwaliteitseisen en kunnen wedijveren met de bekende Zwitserse merken. De onderdelen worden geleverd door gerenommeerde fabrikanten uit Europa en daarbuiten. Een Morval bevat een Swiss made kaliber (STP) dat bekend staat om zijn betrouwbare kwaliteit.';
$home_price = 'Prijs';
$home_price_text = 'Morval staat voor een uitstekende prijs-kwaliteitverhouding';
$shopping_cart_header = 'Winkelwagen';
$about_3_p = 'Morval ontleent zijn naam aan de achternaam van een van Ralphs grootouders. Het logo is geïnspireerd op het monument in het Noord-Franse stadje Morval, dat gebouwd is uit de resten van een kerk en de drie klokken van de toren.';
$newuser_subject = 'MorvalWatches - gebruiker aangemaakt';
$newuser_header = 'Beste gebruiker';
$newuser_text = 'Uw beheerder heeft toegang verleend tot het Klantenportaal.';
$newuser_credential_text_1 = 'Uw account is aangemaakt met gebruikersnaam';
$newuser_credential_text_2 = 'Klik op onderstaande knop om uw registratie te voltooien.';
$newuser_closure = 'Om veiligheidsredenen is deze link slechts 10 minuten actief.';
$verify_account = 'Account verifiëren';
$newuser_signature = ' Met vriendelijke groeten,';
$newuser_signature_name = 'MorvalWatches';
$changeuser_subject = 'MorvalWatches - wachtwoord reset aangevraagd';
$changeuser_header = 'Beste gebruiker';
$changeuser_credential_text_1 = 'Klik op de onderstaande knop om het wachtwoord van uw account opnieuw in te stellen.';
$changeuser_closure = 'Om veiligheidsredenen is deze link slechts 10 minuten actief.';
$changeuser_signature = ' Met vriendelijke groeten,';
$changeuser_signature_name = 'MorvalWatches';
$bracelet_dark = 'Zwart';
$bracelet_blue = 'Donkerblauw';
$bracelet_dark_brown = 'Donkerbruin';
$bracelet_light_brown = 'Lichtbruin';
$bracelet_steel = 'Staal';
$MWTH1NB_description = '<p>De Thomas-I straalt elegantie en verfijning uit. Klassieke afmetingen gecombineerd met subtiele details in de wijzerplaat maken het een bijzondere automatische horloge dat bij elke gelegenheid gedragen kan worden.</p><h3><b>Specificaties</b></h3><ul><li>Kastgrootte: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 met 26 juwelen</li><li>Energiereserve: 40 u</li><li>Isocronisme: &lt; 10 sec./dag</li><li>Lunette: Gepolijst roestvrij staal (316L)</li><li>Waterdicht: 50 meter (5 ATM)</li><li>Wijzerplaat: Zonnestraal-patroon</li><li>Datum: Arabische cijfers (dag)</li><li>Lumen: Superluminova (Blauw)</li><li>Glas: Saffierglas met antireflecterende coating</li><li>Achterkant kast: Geschroefd, geborsteld roestvrij staal met saffierglas</li><li>Band (staal): Geborsteld en gepolijst 316L roestvrij staal</li><li>Band (leer): Handgemaakt Italiaans kalfsleer</li><li>Sluiting: Vouwmechanisme voor ultiem comfort</li><li>Verpakking: Blauwe doos met certificaat en handleiding.</li></ul>';
$MWTH2NB_description = '<p>De Thomas-II biedt een blik op het kloppende hart van het Zwitserse uurwerk. Het benadrukt de precisie en perfectie waarmee de tijd wordt weergegeven.</p><h3><b>Specificaties</b></h3><ul><li>Kastgrootte: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 met 26 juwelen</li><li>Energiereserve: 40 u</li><li>Isocronisme: &lt; 10 sec./dag</li><li>Lunette: Geborsteld roestvrij staal (316L)</li><li>Waterdicht: 50 meter (5 ATM)</li><li>Wijzerplaat: Zonnestraal-patroon</li><li>Lumen: Superluminova (Blauw)</li><li>Glas: Saffierglas met antireflecterende coating</li><li>Achterkant kast: Geschroefd, geborsteld roestvrij staal met saffierglas</li><li>Band (staal): Geborsteld en gepolijst 316L roestvrij staal</li><li>Band (leer): Handgemaakt Italiaans kalfsleer</li><li>Sluiting: Vouwmechanisme voor ultiem comfort</li><li>Verpakking: Blauwe doos met certificaat en handleiding.</li></ul>';
$MWTH2IB_description = '<p>De Thomas-II biedt een blik op het kloppende hart van het Zwitserse uurwerk. Het benadrukt de precisie en perfectie waarmee de tijd wordt weergegeven.</p><h3><b>Specificaties</b></h3><ul><li>Kastgrootte: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 met 26 juwelen</li><li>Energiereserve: 40 u</li><li>Isocronisme: &lt; 10 sec./dag</li><li>Lunette: Geborsteld roestvrij staal (316L)</li><li>Waterdicht: 50 meter (5 ATM)</li><li>Wijzerplaat: Zonnestraal-patroon</li><li>Lumen: Superluminova (Blauw)</li><li>Glas: Saffierglas met antireflecterende coating</li><li>Achterkant kast: Geschroefd, geborsteld roestvrij staal met saffierglas</li><li>Band (staal): Geborsteld en gepolijst 316L roestvrij staal</li><li>Band (leer): Handgemaakt Italiaans kalfsleer</li><li>Sluiting: Vouwmechanisme voor ultiem comfort</li><li>Verpakking: Blauwe doos met certificaat en handleiding.</li></ul>';
$MWTH2RG_description = '<p>De Thomas-II biedt een blik op het kloppende hart van het Zwitserse uurwerk. Het benadrukt de precisie en perfectie waarmee de tijd wordt weergegeven.</p><h3><b>Specificaties</b></h3><ul><li>Kastgrootte: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 met 26 juwelen</li><li>Energiereserve: 40 u</li><li>Isocronisme: &lt; 10 sec./dag</li><li>Lunette: Geborsteld roestvrij staal (316L)</li><li>Waterdicht: 50 meter (5 ATM)</li><li>Wijzerplaat: Zonnestraal-patroon</li><li>Lumen: Superluminova (Blauw)</li><li>Glas: Saffierglas met antireflecterende coating</li><li>Achterkant kast: Geschroefd, geborsteld roestvrij staal met saffierglas</li><li>Band (staal): Geborsteld en gepolijst 316L roestvrij staal</li><li>Band (leer): Handgemaakt Italiaans kalfsleer</li><li>Sluiting: Vouwmechanisme voor ultiem comfort</li><li>Verpakking: Blauwe doos met certificaat en handleiding.</li></ul>';
$MWTH2DG_description = '<p>De Thomas-II biedt een blik op het kloppende hart van het Zwitserse uurwerk. Het benadrukt de precisie en perfectie waarmee de tijd wordt weergegeven.</p><h3><b>Specificaties</b></h3><ul><li>Kastgrootte: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 met 26 juwelen</li><li>Energiereserve: 40 u</li><li>Isocronisme: &lt; 10 sec./dag</li><li>Lunette: Geborsteld roestvrij staal (316L)</li><li>Waterdicht: 50 meter (5 ATM)</li><li>Wijzerplaat: Zonnestraal-patroon</li><li>Lumen: Superluminova (Blauw)</li><li>Glas: Saffierglas met antireflecterende coating</li><li>Achterkant kast: Geschroefd, geborsteld roestvrij staal met saffierglas</li><li>Band (staal): Geborsteld en gepolijst 316L roestvrij staal</li><li>Band (leer): Handgemaakt Italiaans kalfsleer</li><li>Sluiting: Vouwmechanisme voor ultiem comfort</li><li>Verpakking: Blauwe doos met certificaat en handleiding.</li></ul>';
$MWTH2G_description = '<p>De Thomas-II biedt een blik op het kloppende hart van het Zwitserse uurwerk. Het benadrukt de precisie en perfectie waarmee de tijd wordt weergegeven.</p><h3><b>Specificaties</b></h3><ul><li>Kastgrootte: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 met 26 juwelen</li><li>Energiereserve: 40 u</li><li>Isocronisme: &lt; 10 sec./dag</li><li>Lunette: Geborsteld roestvrij staal (316L)</li><li>Waterdicht: 50 meter (5 ATM)</li><li>Wijzerplaat: Zonnestraal-patroon</li><li>Lumen: Superluminova (Blauw)</li><li>Glas: Saffierglas met antireflecterende coating</li><li>Achterkant kast: Geschroefd, geborsteld roestvrij staal met saffierglas</li><li>Band (staal): Geborsteld en gepolijst 316L roestvrij staal</li><li>Band (leer): Handgemaakt Italiaans kalfsleer</li><li>Sluiting: Vouwmechanisme voor ultiem comfort</li><li>Verpakking: Blauwe doos met certificaat en handleiding.</li></ul>';
$MWABRB1_description = 'Armband Handgemaakt Italiaans kalfsleer';
$MWABRDB1_description = 'Armband Handgemaakt Italiaans kalfsleer';
$MWABRLB1_description = 'Armband Handgemaakt Italiaans kalfsleer';
$MWABRBL1_description = 'Armband Handgemaakt Italiaans kalfsleer';
$MWTH1IB_description = '<p>De Thomas-I straalt elegantie en verfijning uit. Klassieke afmetingen gecombineerd met subtiele details in de wijzerplaat maken het een bijzondere automatische horloge dat bij elke gelegenheid gedragen kan worden.</p><h3><b>Specificaties</b></h3><ul><li>Kastgrootte: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 met 26 juwelen</li><li>Energiereserve: 40 u</li><li>Isocronisme: &lt; 10 sec./dag</li><li>Lunette: Gepolijst roestvrij staal (316L)</li><li>Waterdicht: 50 meter (5 ATM)</li><li>Wijzerplaat: Zonnestraal-patroon</li><li>Datum: Arabische cijfers (dag)</li><li>Lumen: Superluminova (Blauw)</li><li>Glas: Saffierglas met antireflecterende coating</li><li>Achterkant kast: Geschroefd, geborsteld roestvrij staal met saffierglas</li><li>Band (staal): Geborsteld en gepolijst 316L roestvrij staal</li><li>Band (leer): Handgemaakt Italiaans kalfsleer</li><li>Sluiting: Vouwmechanisme voor ultiem comfort</li><li>Verpakking: Blauwe doos met certificaat en handleiding.</li></ul>';
$MWTH1RG_description = '<p>De Thomas-I straalt elegantie en verfijning uit. Klassieke afmetingen gecombineerd met subtiele details in de wijzerplaat maken het een bijzondere automatische horloge dat bij elke gelegenheid gedragen kan worden.</p><h3><b>Specificaties</b></h3><ul><li>Kastgrootte: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 met 26 juwelen</li><li>Energiereserve: 40 u</li><li>Isocronisme: &lt; 10 sec./dag</li><li>Lunette: Gepolijst roestvrij staal (316L)</li><li>Waterdicht: 50 meter (5 ATM)</li><li>Wijzerplaat: Zonnestraal-patroon</li><li>Datum: Arabische cijfers (dag)</li><li>Lumen: Superluminova (Blauw)</li><li>Glas: Saffierglas met antireflecterende coating</li><li>Achterkant kast: Geschroefd, geborsteld roestvrij staal met saffierglas</li><li>Band (staal): Geborsteld en gepolijst 316L roestvrij staal</li><li>Band (leer): Handgemaakt Italiaans kalfsleer</li><li>Sluiting: Vouwmechanisme voor ultiem comfort</li><li>Verpakking: Blauwe doos met certificaat en handleiding.</li></ul>';
$MWTH1DG_description = '<p>De Thomas-I straalt elegantie en verfijning uit. Klassieke afmetingen gecombineerd met subtiele details in de wijzerplaat maken het een bijzondere automatische horloge dat bij elke gelegenheid gedragen kan worden.</p><h3><b>Specificaties</b></h3><ul><li>Kastgrootte: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 met 26 juwelen</li><li>Energiereserve: 40 u</li><li>Isocronisme: &lt; 10 sec./dag</li><li>Lunette: Gepolijst roestvrij staal (316L)</li><li>Waterdicht: 50 meter (5 ATM)</li><li>Wijzerplaat: Zonnestraal-patroon</li><li>Datum: Arabische cijfers (dag)</li><li>Lumen: Superluminova (Blauw)</li><li>Glas: Saffierglas met antireflecterende coating</li><li>Achterkant kast: Geschroefd, geborsteld roestvrij staal met saffierglas</li><li>Band (staal): Geborsteld en gepolijst 316L roestvrij staal</li><li>Band (leer): Handgemaakt Italiaans kalfsleer</li><li>Sluiting: Vouwmechanisme voor ultiem comfort</li><li>Verpakking: Blauwe doos met certificaat en handleiding.</li></ul>';
$MWTH1G_description = '<p>De Thomas-I straalt elegantie en verfijning uit. Klassieke afmetingen gecombineerd met subtiele details in de wijzerplaat maken het een bijzondere automatische horloge dat bij elke gelegenheid gedragen kan worden.</p><h3><b>Specificaties</b></h3><ul><li>Kastgrootte: 39 mm x 10,5 mm.</li><li>Kaliber: STP1-11 met 26 juwelen</li><li>Energiereserve: 40 u</li><li>Isocronisme: &lt; 10 sec./dag</li><li>Lunette: Gepolijst roestvrij staal (316L)</li><li>Waterdicht: 50 meter (5 ATM)</li><li>Wijzerplaat: Zonnestraal-patroon</li><li>Datum: Arabische cijfers (dag)</li><li>Lumen: Superluminova (Blauw)</li><li>Glas: Saffierglas met antireflecterende coating</li><li>Achterkant kast: Geschroefd, geborsteld roestvrij staal met saffierglas</li><li>Band (staal): Geborsteld en gepolijst 316L roestvrij staal</li><li>Band (leer): Handgemaakt Italiaans kalfsleer</li><li>Sluiting: Vouwmechanisme voor ultiem comfort</li><li>Verpakking: Blauwe doos met certificaat en handleiding.</li></ul>';
$payment_status_0 = 'Open';
$payment_status_1 = 'Betaald';
$payment_status_101 = 'In behandeling';
$payment_status_102 = 'Mislukt';
$payment_status_103 = 'Verlopen';
$payment_status_999 = 'Geannuleerd';
$payment_method_3 = 'Debet/Credit';
$ad_watch_1 = 'Nederlands design en Zwitsers vakmanschap';
$ad_watch_2 = 'Tijdloze uurwerken die generaties lang meegaan!';
$ad_watch_btn = 'lees verder';
$newsletter_h2 = 'Meld u aan voor de nieuwsbrief';
$newsletter_p = 'Blijf op de hoogte van onze laatste updates, tips en exclusieve aanbiedingen, rechtstreeks in uw inbox.';
$newsletter_confirm = 'Ik heb het privacybeleid gelezen en ga ermee akkoord';
$newsletter_submit = 'indienen';
$header_manufacturing = 'Zwitserse kwaliteit en Nederlandse makelij';
$header_shipping = 'Gratis verzending op al onze horloges';
$header_delivery = 'Snelle service en levering';
$header_rating = 'Klantbeoordeling 4,7/5,0';
?>

View File

@@ -1,220 +0,0 @@
<?php
$h2_brand_name_1 = 'MorvalWatches';
$h2_brand_name_2 = 'a brand with a story';
$h2_brand_visit = 'Visit our collection';
$h2_brand_wow = 'Morval brings together a unique combination of Minimalistic design, Swiss quality and Dutch manufacturing.We give you a watch to wear in any occasion.';
$h1_content_top = 'Our watch collection';
$product_count_1 = 'Product';
$product_count_2 = 's';
$main_filter_category = 'Category';
$main_category = 'All';
$main_filter_sort = 'Sort';
$sort1 = 'A-Z';
$sort2 = 'Z-A';
$sort3 = 'Latest';
$sort4 = 'Oldest';
$sort5 = 'Price High - Low';
$sort6 = 'Price Low - High';
$free_delivery = 'free delivery';
$non_free_delivery = 'free delivery from';
$breadcrum_products = 'Collection';
$product_quantity = 'Quantity';
$product_on_stock = 'In Stock';
$out_of_stock_notify = 'Notify Me';
$out_of_stock_notify_2 = 'Visit us @';
$out_of_stock = 'Out of stock';
$add_to_basket = 'Add To Cart';
$h1_cart_name = 'Shopping Cart';
$h2_cart_suggestions = 'Suggestions';
$h2_cart_sample_product = 'Samples';
$tr_product = 'Product';
$tr_price = 'Price';
$tr_quantity = 'Quantity';
$tr_total = 'Total';
$total_subtotal = 'Subtotal';
$total_note = '(shipping is calculated during checkout)';
$total_vat = 'VAT';
$total_shipping = 'Shipping';
$total_shipping_note = '(shipping included)';
$total_discount = 'Discount';
$total_total = 'Total';
$total_total_note = 'VAT included';
$btn_emptycart = 'clear';
$btn_update = 'Update';
$btn_checkout = 'Checkout';
$navigation_back_to_store = 'return to collection';
$cart_message_empty = 'You have no products added in your Shopping Cart';
$error_account_name = 'Account already exists.';
$error_account_password_rules = 'Password must be between 5 and 20 characters long.';
$error_account_password_match = 'Passwords do not match.';
$error_account = 'Account creation required.';
$h1_checkout = 'Checkout';
$account_available = 'Already have an account?';
$account_log_in = 'Log In';
$account_create = 'Create Account';
$account_create_optional = '(optional)';
$account_create_email = 'Email';
$account_create_password = 'Password';
$account_create_password_confirm = 'Confirm Password';
$h2_Shipping_details = 'Shipping Details';
$h3_shipping_method = 'Shipping Method';
$shipping_first_name = 'First Name';
$shipping_last_name = 'Last Name';
$shipping_address = 'Address';
$shipping_city = 'City';
$shipping_state = 'Region/State';
$shipping_zip = 'Zip';
$shipping_country = 'Country';
$shipping_phone = 'Phone';
$payment_method = 'Payment Method';
$payment_method_1 = 'Debit (NL/BE customers)';
$payment_method_2 = 'Pay on delivery';
$h2_shoppingcart = 'Shopping Cart';
$discount_label = 'Discount Code';
$discount_message = 'Discount code applied!';
$discount_error_1 = 'Incorrect discount code!';
$discount_error_2 = 'Discount code expired!';
$order_consent_1 = 'I would like to recieve email communication about MorvalWatches news, products and services';
$order_consent_2 = 'I agree with';
$order_consent_3 = 'Terms & Conditions';
$btn_place_order = 'Order';
$h1_order_succes_message = 'Your Order Has Been Placed';
$order_succes_message = 'Thank you for ordering with us! We will contact you by email with your order details.';
$error_myaccount = 'Incorrect Email/Password!';
$h1_login = 'Login';
$h1_register = 'Register';
$h1_myaccount = 'My Account';
$h2_menu = 'Menu';
$menu_orders = 'Orders';
$menu_downloads = 'Downloads';
$menu_settings = 'Settings';
$h2_myorders = 'My orders';
$myorders_message = 'You have no orders';
$myorders_order = 'Order';
$myorders_date = 'Date';
$myorders_status = 'Status';
$myorders_shipping = 'Shipping';
$myorders_total = 'Total';
$h2_mydownloads = 'My downloads';
$mydownloads_message = 'You have no downloads';
$mydownloads_product = 'Product';
$h2_settings = 'Settings';
$settings_email = 'Email';
$settings_new_password = 'New Password';
$btn_settings_save = 'Save';
$age_consent_h4 = 'Lets check your age';
$age_consent_text = 'To visit MorvalWatches you need to be 18 years or older.';
$age_consent_btn_allow = 'Agree';
$age_consent_btn_deny = 'disagree';
$maintenanceMode_h4 = 'Webshop is in maintenance';
$maintenanceMode_text = 'Our webshop is in maintenance. We like to see you back soon';
$maintenanceMode_btn = 'OK';
$subject_order_notification = 'MorvalWatches - You have received a new order!';
$subject_new_order = 'MorvalWatches - Order Details';
$subject_out_of_stock = 'MorvalWatches - Out of Stock';
$home_text = 'Home';
$products_text = 'Collection';
$about_text = 'About Us';
$myaccount_text = 'Account';
$social_punch_line = 'Connect with Morval via our social media channels';
$privacy_text = 'Privacy';
$terms_text = 'Terms and Conditions';
$faq_text = 'Frequent asked questions';
$order_email_title = 'MorvalWatches - Order';
$order_email_message_1 = 'Thank you for your order';
$order_email_message_2 = 'Your order has been received and is currently being processed. The details for your order are below.';
$order_email_information = 'Your Details';
$h2_about_1 = 'About Morval';
$h2_about_2 = '';
$about_header_1 = 'About US';
$about_1_p = 'Morval Watches was founded in 2023 by Ralph van Wezel. Ralph is a hospital pharmacist and has a fascination for technology. In his work he strives to make medicines available that make a difference for the patient. Producing a medicine requires knowledge, precision, accuracy, technique, quality and craftsmanship. Herein lies the similarity with the manufacture of a high-quality automatic watch. Ralph has set itself the goal of developing a watch that can compete with the renowned brands, but is sold at an acceptable price.';
$about_header_2 = 'About our watches';
$about_2_p = 'A Morval Watch is inspired by the vintage models and minimalistic design of Scandinavian watches. Due to variations in the color of the dial and straps, a Morval watch can be worn on any occasion, both as sport and dress watch.Morval watches meet the highest quality requirements and can compete with the well-known Swiss brands. The parts are supplied by renowned manufacturers from Europe and beyond. A Morval contains a Swiss-made caliber (STP) that is known for its reliable quality. The assemblies take place in Amsterdam by recognized watchmakers and each watch undergoes extensive quality control for functionality and aesthetics. The watch is manually adjusted and tested to minimize the deviation. Morval stands for an excellent price-quality ratio! When you purchase a Morval watch, you are assured of a timeless timepiece that will last for decades.A lot of attention has been paid to details, such as a brushed case of stainless steel 316 steel, superluminova on the hands, anti-reflective glass and infinitely adjustable leather strap. This translates into the luxurious appearance of the brand. With a Morval Watch you have a unique, robust, stylish and timeless timepiece that will last for generations!';
$about_header_3 = 'About Morval';
$about_morval_text = 'Read more about the history of Morval';
$h2_about_morval_1 = 'The history of Morval';
$h2_about_morval_2 = '';
$about_morval_header_1 = '';
$about_morval_header_2 = '';
$about_morval_header_3 = '';
$about_morval_1_p = '"Morval, a village of 96 inhabitants, is located between 4 communes of the Somme as a peninsula of Pas-de-Calais at the end of the canton of Bapaume.';
$about_morval_2_p = 'When the rubble was cleared, this large empty square remained like a wound in the hearts of the inhabitants. Three years later the municipality built a small campanile where the three bells that were lowered for demolition were hung. Sponsored by 1930s residents, they remain alive and still ring the bell to mark every happy or unfortunate event as we once did.';
$about_morval_3_p = 'When the rubble was cleared, this large empty square remained like a wound in the hearts of the inhabitants. Three years later the municipality built a small campanile where the three bells that were lowered for demolition were hung. Sponsored by 1930s residents, they remain alive and still ring the bell to mark every happy or unfortunate event as we once did. Thanks to them, Morval does not forget its missing bell tower.';
$invoice_morval_subject = 'Morval watches - invoice';
$place_order_header = 'Place order';
$checkout_header = 'Checkout';
$tax_text = 'VAT';
$h2_cart_samples = 'Samples';
$products_filters_h2 = 'Filters';
$btn_filter = 'Filter';
$sort = 'Sort';
$order_number_text = 'Order';
$order_date_text = 'Date';
$tr_options = 'Options';
$order_invoice_text = 'Invoice';
$invoice_payment_paid_text = 'The total amount of this invoice is paid';
$highlight_1 = 'Collection';
$highlight_2 = 'Collection';
$home_timeless = 'Timeless';
$home_timeless_text = 'Morval Watches are unique, robust, stylish and timeless timepieces that will last for generations!';
$shop_action = 'shop now';
$home_quality = 'Quality';
$home_quality_text = 'Morval watches meet the highest quality requirements and can compete with the well-known Swiss brands. The parts are supplied by renowned manufacturers from Europe and beyond. A Morval contains a Swiss-made caliber (STP) that is known for its reliable quality.';
$home_price = 'Price';
$home_price_text = 'Morval stands for an excellent price-quality ratio';
$shopping_cart_header = 'Shopping Cart';
$about_3_p = 'Morval takes its name from the surname of one of Ralphs grandparents. The logo is inspired by the monument in the town of Morval in northern France, which was built from the remains of a church and the three bells from the tower.';
$newuser_subject = 'MorvalWatches - user created';
$newuser_header = 'Dear user';
$newuser_text = 'Your administrator has provided access to the CustomerPortal.';
$newuser_credential_text_1 = 'Your account has been created with username';
$newuser_credential_text_2 = 'Please click the button below to complete your registration.';
$newuser_closure = 'For security reasons this link is only active for 10 minutes.';
$verify_account = 'Verify account';
$newuser_signature = 'Kind regards, ';
$newuser_signature_name = 'MorvalWatches';
$changeuser_subject = 'MorvalWatches - password reset requested';
$changeuser_header = 'Dear user';
$changeuser_credential_text_1 = 'Please click the button below to reset the password of your account.';
$changeuser_closure = 'For security reasons this link is only active for 10 minutes.';
$changeuser_signature = 'Kind regards, ';
$changeuser_signature_name = 'MorvalWatches';
$bracelet_dark = 'Black';
$bracelet_blue = 'Dark Blue';
$bracelet_dark_brown = 'Dark brown';
$bracelet_light_brown = 'Light brown';
$bracelet_steel = 'Steel';
$MWTH1NB_description = '<p>The Thomas-I exudes elegance and sophistication. Classic dimensions combined with subtle details in the dial make it an special automatic watch that can be worn on all occasions.</p><h3><b>Specifications</b></h3><ul><li>Case Size: 39 mm x 10,5 mm.</li><li>Caliber: STP1-11 with 26 jewels</li><li>Power reserve: 40 h</li><li>Isochronism: &lt; 10 sec./day</li><li>Bezel: Polished stainless steel (316L)</li><li>Waterproof: 50 meters (5 ATM)</li><li>Dial: Sunburst dial</li><li>Date: Arabic numbers (day)</li><li>Lumen: Superluminova (Blue)</li><li>Crystal: Sapphire with anti-reflective coating</li><li>Back Case: Screwed, brushed stainless steel with sapphire crystal</li><li>Bracelet (steel): Brushed and polished 316L stainless steel</li><li>Bracelet (Leather): Handmade Italian Calf leather</li><li>Clasp: Folding mechanism for ultimate comfort</li><li>Packaging: Blue box with certificate and manual.</li></ul>';
$MWTH1NB_description = 'Le Thomas-I respire l\'élégance et la sophistication. Des dimensions classiques combinées à des détails subtils sur le cadran en font une montre automatique spéciale qui peut être portée en toutes occasions.SpécificationsTaille du boîtier : 39 mm x 10,5 mm.Calibre : STP1-11 avec 26 rubisRéserve de marche : 40 hIsochronisme : < 10 sec./jourLunette : Acier inoxydable poli (316L)Étanchéité : 50 mètres (5 ATM)Cadran : Cadran soleilléDate : Chiffres arabes (jour)Lumen : Superluminova (bleu)Verre : Saphir avec traitement antirefletFond du boîtier : Acier inoxydable brossé vissé avec verre saphirBracelet (acier) : Brossé et poli Acier inoxydable 316LBracelet (cuir) : Cuir de veau italien fait mainFermoir : Mécanisme pliant pour un confort ultimeEmballage : Boîte bleue avec certificat et manuel.';
$MWTH2NB_description = '<p>The Thomas-II provides a view of the beating heart of the Swiss timepiece. It marks the precision and perfection with which the time is displayed.</p><h3><b>Specifications</b></h3><ul><li>Case Size: 39 mm x 10,5 mm.</li><li>Caliber: STP1-11 with 26 jewels</li><li>Power reserve: 40 h </li><li>Isochronism: &lt; 10 sec./day</li><li>Bezel: Brushed stainless steel (316L)</li><li>Waterproof: 50 meters (5 ATM)</li><li>Dial: Sunburst dial</li><li>Lumen: Superluminova (Blue)</li><li>Crystal: Sapphire with anti-reflective coating </li><li>Back Case: Screwed, brushed stainless steel with sapphire crytal</li><li>Bracelet (steel): Brushed and polished 316L stainless steel</li><li>Bracelet (Leather): Handmade Italian Calf leather</li><li>Clasp: Folding mechanism for ultimate comfort</li><li>Packaging: Blue box with certificate and manual.</li></ul>';
$MWTH2IB_description = '<p>The Thomas-II provides a view of the beating heart of the Swiss timepiece. It marks the precision and perfection with which the time is displayed.</p><h3><b>Specifications</b></h3><ul><li>Case Size: 39 mm x 10,5 mm.</li><li>Caliber: STP1-11 with 26 jewels</li><li>Power reserve: 40 h </li><li>Isochronism: &lt; 10 sec./day</li><li>Bezel: Brushed stainless steel (316L)</li><li>Waterproof: 50 meters (5 ATM)</li><li>Dial: Sunburst dial</li><li>Lumen: Superluminova (Blue)</li><li>Crystal: Sapphire with anti-reflective coating </li><li>Back Case: Screwed, brushed stainless steel with sapphire crytal</li><li>Bracelet (steel): Brushed and polished 316L stainless steel</li><li>Bracelet (Leather): Handmade Italian Calf leather</li><li>Clasp: Folding mechanism for ultimate comfort</li><li>Packaging: Blue box with certificate and manual.</li></ul>';
$MWTH2RG_description = '<p>The Thomas-II provides a view of the beating heart of the Swiss timepiece. It marks the precision and perfection with which the time is displayed.</p><h3><b>Specifications</b></h3><ul><li>Case Size: 39 mm x 10,5 mm.</li><li>Caliber: STP1-11 with 26 jewels</li><li>Power reserve: 40 h </li><li>Isochronism: &lt; 10 sec./day</li><li>Bezel: Brushed stainless steel (316L)</li><li>Waterproof: 50 meters (5 ATM)</li><li>Dial: Sunburst dial</li><li>Lumen: Superluminova (Blue)</li><li>Crystal: Sapphire with anti-reflective coating </li><li>Back Case: Screwed, brushed stainless steel with sapphire crytal</li><li>Bracelet (steel): Brushed and polished 316L stainless steel</li><li>Bracelet (Leather): Handmade Italian Calf leather</li><li>Clasp: Folding mechanism for ultimate comfort</li><li>Packaging: Blue box with certificate and manual.</li></ul>';
$MWTH2DG_description = '<p>The Thomas-II provides a view of the beating heart of the Swiss timepiece. It marks the precision and perfection with which the time is displayed.</p><h3><b>Specifications</b></h3><ul><li>Case Size: 39 mm x 10,5 mm.</li><li>Caliber: STP1-11 with 26 jewels</li><li>Power reserve: 40 h </li><li>Isochronism: &lt; 10 sec./day</li><li>Bezel: Brushed stainless steel (316L)</li><li>Waterproof: 50 meters (5 ATM)</li><li>Dial: Sunburst dial</li><li>Lumen: Superluminova (Blue)</li><li>Crystal: Sapphire with anti-reflective coating </li><li>Back Case: Screwed, brushed stainless steel with sapphire crytal</li><li>Bracelet (steel): Brushed and polished 316L stainless steel</li><li>Bracelet (Leather): Handmade Italian Calf leather</li><li>Clasp: Folding mechanism for ultimate comfort</li><li>Packaging: Blue box with certificate and manual.</li></ul>';
$MWTH2G_description = '<p>The Thomas-II provides a view of the beating heart of the Swiss timepiece. It marks the precision and perfection with which the time is displayed.</p><h3><b>Specifications</b></h3><ul><li>Case Size: 39 mm x 10,5 mm.</li><li>Caliber: STP1-11 with 26 jewels</li><li>Power reserve: 40 h </li><li>Isochronism: &lt; 10 sec./day</li><li>Bezel: Brushed stainless steel (316L)</li><li>Waterproof: 50 meters (5 ATM)</li><li>Dial: Sunburst dial</li><li>Lumen: Superluminova (Blue)</li><li>Crystal: Sapphire with anti-reflective coating </li><li>Back Case: Screwed, brushed stainless steel with sapphire crytal</li><li>Bracelet (steel): Brushed and polished 316L stainless steel</li><li>Bracelet (Leather): Handmade Italian Calf leather</li><li>Clasp: Folding mechanism for ultimate comfort</li><li>Packaging: Blue box with certificate and manual.</li></ul>';
$MWABRB1_description = 'Bracelet Handmade Italian Calf leather';
$MWABRDB1_description = 'Bracelet Handmade Italian Calf leather';
$MWABRLB1_description = 'Bracelet Handmade Italian Calf leather';
$MWABRBL1_description = 'Bracelet Handmade Italian Calf leather';
$MWTH1IB_description = '<p>The Thomas-I exudes elegance and sophistication. Classic dimensions combined with subtle details in the dial make it an special automatic watch that can be worn on all occasions.</p><h3><b>Specifications</b></h3><ul><li>Case Size: 39 mm x 10,5 mm.</li><li>Caliber: STP1-11 with 26 jewels</li><li>Power reserve: 40 h</li><li>Isochronism: &lt; 10 sec./day</li><li>Bezel: Polished stainless steel (316L)</li><li>Waterproof: 50 meters (5 ATM)</li><li>Dial: Sunburst dial</li><li>Date: Arabic numbers (day)</li><li>Lumen: Superluminova (Blue)</li><li>Crystal: Sapphire with anti-reflective coating</li><li>Back Case: Screwed, brushed stainless steel with sapphire crystal</li><li>Bracelet (steel): Brushed and polished 316L stainless steel</li><li>Bracelet (Leather): Handmade Italian Calf leather</li><li>Clasp: Folding mechanism for ultimate comfort</li><li>Packaging: Blue box with certificate and manual.</li></ul>';
$MWTH1RG_description = '<p>The Thomas-I exudes elegance and sophistication. Classic dimensions combined with subtle details in the dial make it an special automatic watch that can be worn on all occasions.</p><h3><b>Specifications</b></h3><ul><li>Case Size: 39 mm x 10,5 mm.</li><li>Caliber: STP1-11 with 26 jewels</li><li>Power reserve: 40 h</li><li>Isochronism: &lt; 10 sec./day</li><li>Bezel: Polished stainless steel (316L)</li><li>Waterproof: 50 meters (5 ATM)</li><li>Dial: Sunburst dial</li><li>Date: Arabic numbers (day)</li><li>Lumen: Superluminova (Blue)</li><li>Crystal: Sapphire with anti-reflective coating</li><li>Back Case: Screwed, brushed stainless steel with sapphire crystal</li><li>Bracelet (steel): Brushed and polished 316L stainless steel</li><li>Bracelet (Leather): Handmade Italian Calf leather</li><li>Clasp: Folding mechanism for ultimate comfort</li><li>Packaging: Blue box with certificate and manual.</li></ul>';
$MWTH1DG_description = '<p>The Thomas-I exudes elegance and sophistication. Classic dimensions combined with subtle details in the dial make it an special automatic watch that can be worn on all occasions.</p><h3><b>Specifications</b></h3><ul><li>Case Size: 39 mm x 10,5 mm.</li><li>Caliber: STP1-11 with 26 jewels</li><li>Power reserve: 40 h</li><li>Isochronism: &lt; 10 sec./day</li><li>Bezel: Polished stainless steel (316L)</li><li>Waterproof: 50 meters (5 ATM)</li><li>Dial: Sunburst dial</li><li>Date: Arabic numbers (day)</li><li>Lumen: Superluminova (Blue)</li><li>Crystal: Sapphire with anti-reflective coating</li><li>Back Case: Screwed, brushed stainless steel with sapphire crystal</li><li>Bracelet (steel): Brushed and polished 316L stainless steel</li><li>Bracelet (Leather): Handmade Italian Calf leather</li><li>Clasp: Folding mechanism for ultimate comfort</li><li>Packaging: Blue box with certificate and manual.</li></ul>';
$MWTH1G_description = '<p>The Thomas-I exudes elegance and sophistication. Classic dimensions combined with subtle details in the dial make it an special automatic watch that can be worn on all occasions.</p><h3><b>Specifications</b></h3><ul><li>Case Size: 39 mm x 10,5 mm.</li><li>Caliber: STP1-11 with 26 jewels</li><li>Power reserve: 40 h</li><li>Isochronism: &lt; 10 sec./day</li><li>Bezel: Polished stainless steel (316L)</li><li>Waterproof: 50 meters (5 ATM)</li><li>Dial: Sunburst dial</li><li>Date: Arabic numbers (day)</li><li>Lumen: Superluminova (Blue)</li><li>Crystal: Sapphire with anti-reflective coating</li><li>Back Case: Screwed, brushed stainless steel with sapphire crystal</li><li>Bracelet (steel): Brushed and polished 316L stainless steel</li><li>Bracelet (Leather): Handmade Italian Calf leather</li><li>Clasp: Folding mechanism for ultimate comfort</li><li>Packaging: Blue box with certificate and manual.</li></ul>';
$payment_status_0 = 'Open';
$payment_status_1 = 'Paid';
$payment_status_101 = 'Pending';
$payment_status_102 = 'Failed';
$payment_status_103 = 'Expired';
$payment_status_999 = 'Cancelled';
$payment_method_3 = 'Debit/Credit';
$ad_watch_1 = 'Dutch design and Swiss craftsmanship';
$ad_watch_2 = 'Timeless timepieces that will last for generations!';
$ad_watch_btn = 'read more';
$newsletter_h2 = 'Sign up for<br>the newsletter';
$newsletter_p = 'Stay connected with our latest updates, tips, and exclusive offers—straight to your inbox.';
$newsletter_confirm = 'I have read and agree with the privacy policy';
$newsletter_submit = 'submit';
$header_manufacturing = 'Swiss quality and Dutch manufacturing';
$header_shipping = 'Free shipping on all of our watches';
$header_delivery = 'Fast service and delivery';
$header_rating = 'Client rate 4.7/5.0';
?>

View File

@@ -1,38 +1,205 @@
<?php
// Prevent direct access to file
defined(security_key) or exit;
// Remove all the products in cart, the variable is no longer needed as the order has been processed
if (isset($_SESSION['cart'])) {
unset($_SESSION['cart']);
}
// Remove discount code
if (isset($_SESSION['discount'])) {
unset($_SESSION['discount']);
// Get order ID and payment status
$order_id = $_SESSION['pending_order_id'] ?? $_GET['order_id'] ?? null;
$payment_status = $_GET['payment'] ?? 'processing';
$view = template_header(($place_order_header ?? 'Order Status'),'');
// Check payment status if we have an order ID
// Only check API if payment status is not already set to 'failed' from retry timeout
if ($order_id && $payment_status !== 'failed') {
$transaction_data = ioAPIv2('/v2/transactions/txn_id='.$order_id,'',$clientsecret);
$transaction = json_decode($transaction_data, true);
if ($transaction && isset($transaction[0])) {
$payment_status_code = $transaction[0]['payment_status'] ?? 0;
// Map payment status codes: 1 = Paid, 101 = Pending, 102 = Failed, 103 = Expired, 999 = Cancelled
if ($payment_status_code == 1) {
$payment_status = 'success';
} elseif ($payment_status_code == 101) {
$payment_status = 'pending';
} elseif (in_array($payment_status_code, [102, 103, 999])) {
$payment_status = 'failed';
}
}
}
$view = template_header(($place_order_header ?? 'Place order'),'');
if ($error){
// Display appropriate message based on payment status
if ($payment_status === 'success') {
// Payment successful - clear cart and show success
if (isset($_SESSION['cart'])) {
unset($_SESSION['cart']);
}
if (isset($_SESSION['discount'])) {
unset($_SESSION['discount']);
}
if (isset($_SESSION['pending_order_id'])) {
unset($_SESSION['pending_order_id']);
}
$view .= '
<p class="content-wrapper error">'.$error.'</p>';
}
else{
$view .= '
<div class="order-confirmation">
<div class="order-confirmation__container">
<div class="order-confirmation__icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="48" height="48" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
<polyline points="22 4 12 14.01 9 11.01"></polyline>
</svg>
<div class="status-container">
<div class="status-card success">
<div class="status-icon success-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="80" height="80">
<circle cx="12" cy="12" r="11" fill="#10b981" stroke="" stroke-width="2"/>
<path d="M7 12l3.5 3.5L17 8" stroke="white" stroke-width="3" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
<h1 class="status-title success-title">'.($payment_success_title ?? 'Payment Successful!').'</h1>
<p class="status-message">'.($payment_success_message ?? 'Your order has been confirmed and an email confirmation has been sent to your email address.').'</p>
'.($order_id ? '<div class="order-number">'.($order_number_label ?? 'Order number').': <strong>#'.$order_id.'</strong></div>' : '').'
<div class="status-actions">
<a href="'.url('index.php').'" class="btn btn-primary">
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
<path d="M7.5 15L2.5 10L7.5 5M3 10H17.5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
'.($continue_shopping_btn ?? 'Continue Shopping').'
</a>
</div>
</div>
</div>';
} elseif ($payment_status === 'pending') {
// Payment pending
$view .= '
<div class="status-container">
<div class="status-card pending">
<div class="status-icon pending-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="80" height="80">
<circle cx="12" cy="12" r="11" fill="#f59e0b" stroke="" stroke-width="2"/>
<circle cx="12" cy="12" r="3" fill="white"/>
<path d="M12 6v6l4 2" stroke="white" stroke-width="2.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
<h1 class="status-title pending-title">'.($payment_pending_title ?? 'Payment Pending').'</h1>
<p class="status-message">'.($payment_pending_message ?? 'Your order has been received and is awaiting payment confirmation. You will receive an email once the payment is confirmed.').'</p>
'.($order_id ? '<div class="order-number">'.($order_number_label ?? 'Order number').': <strong>#'.$order_id.'</strong></div>' : '').'
<div class="status-actions">
<a href="'.url('index.php').'" class="btn btn-primary">
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
<path d="M7.5 15L2.5 10L7.5 5M3 10H17.5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
'.($continue_shopping_btn ?? 'Continue Shopping').'
</a>
</div>
</div>
<h1 class="order-confirmation__title">'.$h1_order_succes_message.'</h1>
<p class="order-confirmation__message">'.$order_succes_message.'</p>
</div>
<script>
let checkInterval;
let checkCount = 0;
const maxChecks = 5;
function checkPaymentStatus() {
if (checkCount >= maxChecks) {
clearInterval(checkInterval);
window.location.href = "'.url('placeorder/'.$order_id).'?payment=failed";
return;
}
checkCount++;
fetch("'.base_url.'api_check_payment_status.php?order_id='.$order_id.'")
.then(response => response.json())
.then(data => {
if (data.status !== "pending") {
clearInterval(checkInterval);
window.location.href = "'.url('placeorder/'.$order_id).'?payment=" + data.status;
}
})
.catch(error => {
console.error("Error checking payment status:", error);
});
}
// Check immediately, then every 3 seconds
checkPaymentStatus();
checkInterval = setInterval(checkPaymentStatus, 3000);
</script>';
} elseif ($payment_status === 'processing') {
// Payment is being processed
$view .= '
<div class="status-container">
<div class="status-card processing">
<div class="status-icon processing-icon">
<svg class="spinner" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="80" height="80">
<circle cx="12" cy="12" r="10" stroke="#3b82f6" stroke-width="4" fill="none" stroke-dasharray="60" stroke-linecap="round">
<animateTransform attributeName="transform" type="rotate" from="0 12 12" to="360 12 12" dur="1s" repeatCount="indefinite"/>
</circle>
</svg>
</div>
<h1 class="status-title processing-title">'.($payment_processing_title ?? 'Processing Payment...').'</h1>
<p class="status-message">'.($payment_processing_message ?? 'Please wait while we confirm your payment. This may take a few moments.').'</p>
<div class="progress-bar">
<div class="progress-fill"></div>
</div>
</div>
</div>
';
<script>
let checkInterval;
let checkCount = 0;
const maxChecks = 5;
function checkPaymentStatus() {
if (checkCount >= maxChecks) {
clearInterval(checkInterval);
window.location.href = "'.url('placeorder/'.$order_id).'?payment=failed";
return;
}
checkCount++;
fetch("'.base_url.'api_check_payment_status.php?order_id='.$order_id.'")
.then(response => response.json())
.then(data => {
if (data.status !== "processing") {
clearInterval(checkInterval);
window.location.href = "'.url('placeorder/'.$order_id).'?payment=" + data.status;
}
})
.catch(error => {
console.error("Error checking payment status:", error);
});
}
// Check immediately, then every 3 seconds
checkPaymentStatus();
checkInterval = setInterval(checkPaymentStatus, 3000);
</script>';
} else {
// Payment failed
$view .= '
<div class="status-container">
<div class="status-card failed">
<div class="status-icon failed-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="80" height="80">
<circle cx="12" cy="12" r="11" fill="#ef4444" stroke="" stroke-width="2"/>
<path d="M8 8l8 8M16 8l-8 8" stroke="white" stroke-width="3" stroke-linecap="round"/>
</svg>
</div>
<h1 class="status-title failed-title">'.($payment_failed_title ?? 'Payment Not Successful').'</h1>
<p class="status-message">'.($payment_failed_message ?? 'Unfortunately, your payment could not be processed. Please try again or choose a different payment method.').'</p>
'.($order_id ? '<div class="order-number">'.($order_number_label ?? 'Order reference').': <strong>#'.$order_id.'</strong></div>' : '').'
<div class="status-actions">
<a href="'.url('index.php?page=checkout').'" class="btn btn-primary">
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
<path d="M7.5 15L2.5 10L7.5 5M3 10H17.5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
'.($return_to_checkout_btn ?? 'Return to Checkout').'
</a>
<a href="'.url('index.php?page=cart').'" class="btn btn-secondary">'.($view_cart_btn ?? 'View Cart').'</a>
</div>
</div>
</div>';
}
$view .= template_footer();
echo $view;
echo $view;
?>

View File

@@ -5,10 +5,17 @@ defined(security_key) or exit;
// Check to make sure the id parameter is specified in the URL
if (isset($_GET['id'])) {
//GET CATALOG DATA
$product = ioAPIv2('/v2/catalog/product_id='.$_GET['id'],'',$clientsecret);
$product = json_decode($product,true);
$product = $product[0] ?? '';
//GET CATALOG DATA FROM CACHE
$all_products = $GLOBALS['cached_catalog'];
// Find the specific product by ID or slug
$product = null;
foreach ($all_products as $prod) {
if ($prod['rowID'] == $_GET['id'] || (isset($prod['url_slug']) && $prod['url_slug'] == $_GET['id'])) {
$product = $prod;
break;
}
}
// Check if the product exists (array is not empty)
if (!$product) {
@@ -89,42 +96,76 @@ $view .='<p class="content-wrapper error">'.$error.'</p>';
}
else {
$view .='
<div class="product content-wrapper">
<div class="product-imgs">';
if (isset($_GET['option_id']) && !empty($_GET['option_id']) && $_GET['option_id'] !=''){
$fullPath = null;
<div class="product content-wrapper">
<div class="product-mobile-header">
<div class="breadcrum">
<a href="'.$products_link.'">'.$breadcrum_products.'</a> <p>/ '.(${$product['productname']} ?? $product['productname']).'</p>
</div>
<h1 class="name">'.(${$product['productname']} ?? $product['productname']).'</h1>
</div>
<div class="product-imgs carousel-container">';
// Determine the main image source
$mainImageSrc = '';
$mainImageAlt = '';
if (isset($_GET['option_id']) && !empty($_GET['option_id']) && $_GET['option_id'] !=''){
foreach ($product['configurations'] as $configuration) {
if (isset($configuration['attributes'])) {
foreach ($configuration['attributes'] as $attribute) {
if ($attribute['attribute_id'] == $_GET['option_id']) {
$fullPath = $attribute['alternative_media_full_path'] ?? $attribute['full_path'];
$altTitle = $attribute['alternative_media_title'] ?? $attribute['title'];
$view .='
<div class="product-img-large">
<img src="'.img_url.$fullPath.'" id="'.$product['rowID'].'" alt="'.$altTitle.'">
</div>';
break 2; // Exit all loops once found
$mainImageSrc = img_url . ($attribute['alternative_media_full_path'] ?? $attribute['full_path']);
$mainImageAlt = $attribute['alternative_media_title'] ?? $attribute['title'];
break 2;
}
}
}
}
} elseif (isset($product['full_path']) && $product['full_path'] != ''){
}
// Fallback to product main image if no option_id or not found
if (empty($mainImageSrc) && isset($product['full_path']) && $product['full_path'] != '') {
$mainImageSrc = img_url . $product['full_path'];
$mainImageAlt = ${$product['productname']} ?? $product['productname'];
}
// Render carousel with arrows if we have an image
if (!empty($mainImageSrc)) {
$view .='
<div class="product-img-large">
<img src="'.img_url.$product['full_path'].'" id="'.$product['rowID'].'" alt="'.(${$product['productname']} ?? $product['productname']).'">
<div class="product-img-large carousel-main">
<button class="carousel-arrow left" aria-label="Previous image">&#8592;</button>
<img src="'.$mainImageSrc.'" id="'.$product['rowID'].'" alt="'.$mainImageAlt.'">
<button class="carousel-arrow right" aria-label="Next image">&#8594;</button>
</div>';
}
$view .='
<div class="product-small-imgs">';
//Show small images
foreach ($product_media as $media){
$view .=' <div class="product-img-small '.($media['position']==1?' selected':'').'">
<img src="'.img_url.$media['full_path'].'" width="150" height="150" alt="">
</div>';
<div class="product-small-imgs carousel-thumbnails">';
// Add the main product image as the first thumbnail
$thumbs = [];
if (isset($_GET['option_id']) && !empty($_GET['option_id']) && $_GET['option_id'] !=''){
foreach ($product['configurations'] as $configuration) {
if (isset($configuration['attributes'])) {
foreach ($configuration['attributes'] as $attribute) {
if ($attribute['attribute_id'] == $_GET['option_id']) {
$mainPath = $attribute['alternative_media_full_path'] ?? $attribute['full_path'];
$mainAltTitle = $attribute['alternative_media_title'] ?? $attribute['title'];
$thumbs[] = ['src' => img_url.$mainPath, 'alt' => $mainAltTitle, 'selected' => true];
break 2;
}
}
}
}
} elseif (isset($product['full_path']) && $product['full_path'] != ''){
$thumbs[] = ['src' => img_url.$product['full_path'], 'alt' => (${$product['productname']} ?? $product['productname']), 'selected' => true];
}
foreach ($product_media as $media){
$thumbs[] = ['src' => img_url.$media['full_path'], 'alt' => '', 'selected' => false];
}
foreach ($thumbs as $i => $thumb) {
$sel = $thumb['selected'] ? ' selected' : '';
$view .= ' <div class="product-img-small'.$sel.'" data-index="'.$i.'">
<img src="'.$thumb['src'].'" width="80" height="80" alt="'.$thumb['alt'].'">
</div>';
}
$view .='
</div>
</div>
@@ -178,33 +219,35 @@ $view .='<form id="product-form" action="" method="post">';
$output ='';
foreach ($configuration['attributes'] as $attribute){
// Check if this option should be pre-selected
$isChecked = (isset($_GET['option_id']) && $_GET['option_id'] == $attribute['attribute_id']) ? ' checked' : '';
if(isset($attribute['full_path']) && $attribute['full_path'] !=''){
$onclick ='';
//ADD updateOption to change pictures when GROUP is IN configuration
if(isset($product['config_setting']) && $product['config_setting'] == $configuration['assignment']){
$IMG_large_id = img_url.$attribute['alternative_media_full_path']; //URL TO LARGE IMAGE
$onclick = 'onclick="updateOption(\''.$product['rowID'].'\',\''.$IMG_large_id.'\')"';
}
$IMG_small_id = img_url.$attribute['full_path']; //URL TO SMALL IMAGE
$output .= '
<label class="picture_select_label">
<input id="'.$attribute['attribute_id'].'" class="option radio" value="'.$attribute['attribute_id'].'" name="product[option]['.$configuration['assignment'].'][]" type="radio" data-price="'.($attribute['price'] ?? 0).'" data-rrp="'.($attribute['rrp'] ?? 0).'" data-modifier="'.($attribute['price_modifier'] ?? 1).'" '.(($configuration['group_mandatory'] == 1 ) ? ' required' : '').'>
<input id="'.$attribute['attribute_id'].'" class="option radio" value="'.$attribute['attribute_id'].'" name="product[option]['.$configuration['assignment'].'][]" type="radio" data-price="'.($attribute['price'] ?? 0).'" data-rrp="'.($attribute['rrp'] ?? 0).'" data-modifier="'.($attribute['price_modifier'] ?? 1).'" '.(($configuration['group_mandatory'] == 1 ) ? ' required' : '').$isChecked.'>
<span class="picture_select"><img '.$onclick.' src="'.$IMG_small_id.'"></span>
</label>';
</label>';
} else {
$output .= '
<label>
<input id="'.$attribute['attribute_id'].'>" class="option radio" value="'.$attribute['attribute_id'].'" name="product[option]['.$configuration['assignment'].'][]" type="radio" data-price="'.($attribute['price'] ?? 0).'" data-rrp="'.($attribute['rrp'] ?? 0).'" data-modifier="'.($attribute['price_modifier'] ?? 1).'" '.(($configuration['group_mandatory'] == 1 ) ? ' required' : '').'>'.(${$attribute['item_name']} ?? $attribute['item_name']).'
</label>';
<input id="'.$attribute['attribute_id'].'>" class="option radio" value="'.$attribute['attribute_id'].'" name="product[option]['.$configuration['assignment'].'][]" type="radio" data-price="'.($attribute['price'] ?? 0).'" data-rrp="'.($attribute['rrp'] ?? 0).'" data-modifier="'.($attribute['price_modifier'] ?? 1).'" '.(($configuration['group_mandatory'] == 1 ) ? ' required' : '').$isChecked.'>'.(${$attribute['item_name']} ?? $attribute['item_name']).'
</label>';
}
}
$view .= '<div class="radio-checkbox">'.$output.'</div>';
@@ -213,68 +256,75 @@ $view .='<form id="product-form" action="" method="post">';
$output ='';
foreach ($configuration['attributes'] as $attribute){
// Check if this option should be pre-selected
$isChecked = (isset($_GET['option_id']) && $_GET['option_id'] == $attribute['attribute_id']) ? ' checked' : '';
if(isset($attribute['full_path']) && $attribute['full_path'] !=''){
$onclick ='';
//ADD updateOption to change pictures when GROUP is IN configuration
if(isset($product['config_setting']) && $product['config_setting'] == $configuration['assignment']){
$IMG_large_id = img_url.$attribute['alternative_media_full_path']; //URL TO LARGE IMAGE
$onclick = 'onclick="updateOption(\''.$product['rowID'].'\',\''.$IMG_large_id.'\')"';
}
$IMG_small_id = img_url.$attribute['full_path']; //URL TO SMALL IMAGE
$output .= '
<label class="picture_select_label">
<input id="'.$attribute['attribute_id'].'>" class="option checkbox" value="'.$attribute['attribute_id'].'" name="product[option]['.$configuration['assignment'].'][]" type="checkbox" data-price="'.($attribute['price'] ?? 0).'" data-rrp="'.($attribute['rrp'] ?? 0).'" data-modifier="'.($attribute['price_modifier'] ?? 1).'" '.(($configuration['group_mandatory'] == 1 ) ? ' required' : '').'>
<input id="'.$attribute['attribute_id'].'>" class="option checkbox" value="'.$attribute['attribute_id'].'" name="product[option]['.$configuration['assignment'].'][]" type="checkbox" data-price="'.($attribute['price'] ?? 0).'" data-rrp="'.($attribute['rrp'] ?? 0).'" data-modifier="'.($attribute['price_modifier'] ?? 1).'" '.(($configuration['group_mandatory'] == 1 ) ? ' required' : '').$isChecked.'>
<span class="picture_select"><img '.$onclick.' src="'.$IMG_small_id.'"></span>
</label>';
</label>';
} else {
$output .= '
<label>
<input id="'.$attribute['attribute_id'].'>" class="option checkbox" value="'.$attribute['attribute_id'].'" name="product[option]['.$configuration['assignment'].'][]" type="checkbox" data-price="'.($attribute['price'] ?? 0).'" data-rrp="'.($attribute['rrp'] ?? 0).'" data-modifier="'.($attribute['price_modifier'] ?? 1).'" '.(($configuration['group_mandatory'] == 1 ) ? ' required' : '').'>'.(${$attribute['item_name']} ?? $attribute['item_name']).'
</label>';
<input id="'.$attribute['attribute_id'].'>" class="option checkbox" value="'.$attribute['attribute_id'].'" name="product[option]['.$configuration['assignment'].'][]" type="checkbox" data-price="'.($attribute['price'] ?? 0).'" data-rrp="'.($attribute['rrp'] ?? 0).'" data-modifier="'.($attribute['price_modifier'] ?? 1).'" '.(($configuration['group_mandatory'] == 1 ) ? ' required' : '').$isChecked.'>'.(${$attribute['item_name']} ?? $attribute['item_name']).'
</label>';
}
}
$view .= '<div class="radio-checkbox">'.$output.'</div>';
break;
case 2: //Dropdown
// Check if any option is pre-selected via URL
$hasPreselection = isset($_GET['option_id']) && !empty($_GET['option_id']);
$output ='
<select id="'.$configuration['assignment'].'" class="option select" name="product[option]['.$configuration['assignment'].']" '.(($configuration['group_mandatory'] == 1 ) ? ' required' : '').'>
<option value="" selected disabled style="display:none">'.$configuration['assignment_name'].'</option>
<option value=""'.($hasPreselection ? '' : ' selected').' disabled style="display:none">'.$configuration['assignment_name'].'</option>
';
foreach ($configuration['attributes'] as $attribute){
// Check if this option should be pre-selected
$isSelected = (isset($_GET['option_id']) && $_GET['option_id'] == $attribute['attribute_id']) ? ' selected' : '';
if(isset($attribute['full_path']) && $attribute['full_path'] !=''){
$onclick ='';
//ADD updateOption to change pictures when GROUP is IN configuration
if(isset($product['config_setting']) && $product['config_setting'] == $configuration['assignment']){
$IMG_large_id = img_url.$attribute['alternative_media_full_path']; //URL TO LARGE IMAGE
$onclick = 'onclick="updateOption(\''.$product['rowID'].'\',\''.$IMG_large_id.'\')"';
}
$IMG_small_id = img_url.$attribute['full_path']; //URL TO SMALL IMAGE
$output .= '
<option id="'.$attribute['attribute_id'].'" value="'.$attribute['attribute_id'].'" data-price="'.($attribute['price'] ?? 0).'" data-rrp="'.($attribute['rrp'] ?? 0).'" data-modifier="'.($attribute['price_modifier'] ?? 1).'">'.(${$attribute['item_name']} ?? $attribute['item_name']).'</option>';
<option id="'.$attribute['attribute_id'].'" value="'.$attribute['attribute_id'].'" data-price="'.($attribute['price'] ?? 0).'" data-rrp="'.($attribute['rrp'] ?? 0).'" data-modifier="'.($attribute['price_modifier'] ?? 1).'"'.$isSelected.'>'.(${$attribute['item_name']} ?? $attribute['item_name']).'</option>';
} else {
$output .= '
<option id="'.$attribute['attribute_id'].'" value="'.$attribute['attribute_id'].'" data-price="'.($attribute['price'] ?? 0).'" data-rrp="'.($attribute['rrp'] ?? 0).'" data-modifier="'.($attribute['price_modifier'] ?? 1).'">'.(${$attribute['item_name']} ?? $attribute['item_name']).'</option>';
<option id="'.$attribute['attribute_id'].'" value="'.$attribute['attribute_id'].'" data-price="'.($attribute['price'] ?? 0).'" data-rrp="'.($attribute['rrp'] ?? 0).'" data-modifier="'.($attribute['price_modifier'] ?? 1).'"'.$isSelected.'>'.(${$attribute['item_name']} ?? $attribute['item_name']).'</option>';
}
}
$view .= $output.'</select></div>';
@@ -290,16 +340,325 @@ $view .='
<input id="product" type="hidden" name="product[product]" value="'.$product['rowID'].'">
<input id="product" type="hidden" name="product[version]" value="'.($product['version_id'] ?? '').'">
<input type="submit" value="'.$add_to_basket.'" class="btn">
<input type="submit" value="'.$add_to_basket.'" class="btn add-to-basket-sticky">
</form>
<div class="description">
'.(${$product['productdescription']} ?? $product['productdescription']).'
</div>
</div>
</div>
</div>';
$view .= '<style>
/* Mobile Header - Hidden on desktop */
.product-mobile-header {
display: none;
}
/* Carousel Container */
.carousel-container {
position: relative;
display: flex;
flex-direction: column;
}
/* Main Image Area */
.carousel-main {
display: flex;
align-items: center;
justify-content: center;
position: relative;
background-color: #f8f8f8;
border-radius: 8px;
padding: 1rem;
overflow: hidden;
min-height: 300px;
}
.carousel-main img {
max-width: 100%;
max-height: 450px;
object-fit: contain;
border-radius: 8px;
transition: opacity 0.3s ease;
user-select: none;
-webkit-user-drag: none;
}
/* Carousel Arrows */
.carousel-arrow {
background: rgba(255, 255, 255, 0);
border: none;
font-size: 1.5rem;
padding: 0.75rem 1rem;
cursor: pointer;
position: absolute;
top: 50%;
transform: translateY(-50%);
z-index: 10;
border-radius: 50%;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
transition: all 0.2s ease;
color: #1a3a5f;
line-height: 1;
}
.carousel-arrow:hover {
background: #fff;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
transform: translateY(-50%) scale(1.1);
}
.carousel-arrow.left { left: 10px; }
.carousel-arrow.right { right: 10px; }
/* Thumbnails Container */
.carousel-thumbnails {
display: flex;
flex-direction: row;
gap: 10px;
justify-content: center;
align-items: center;
margin-top: 15px;
padding: 10px 0;
overflow-x: auto;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
scrollbar-width: thin;
scrollbar-color: #ccc transparent;
}
.carousel-thumbnails::-webkit-scrollbar {
height: 6px;
}
.carousel-thumbnails::-webkit-scrollbar-track {
background: transparent;
}
.carousel-thumbnails::-webkit-scrollbar-thumb {
background-color: #ccc;
border-radius: 3px;
}
/* Thumbnail Items */
.product-img-small {
flex-shrink: 0;
width: 70px;
height: 70px;
border: 2px solid transparent;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s ease;
overflow: hidden;
opacity: 0.6;
}
.product-img-small:hover {
border-color: #1a3a5f;
opacity: 0.9;
}
.product-img-small.selected {
border-color: #1a3a5f;
opacity: 1;
box-shadow: 0 2px 8px rgba(26, 58, 95, 0.3);
}
.product-img-small img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
/* Sticky Add to Basket Button */
.add-to-basket-sticky {
transition: all 0.3s ease;
}
.add-to-basket-sticky.is-sticky {
position: fixed;
left: 0;
right: 0;
bottom: 0;
width: 100%;
z-index: 1000;
border-radius: 0;
margin: 0;
padding: 1rem 2rem;
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.15);
}
/* Tablet/Mobile Responsive Styles (< 993px) */
@media (max-width: 992px) {
/* Hide info bar on tablet/mobile */
.top-info-bar,
.info-bar {
display: none !important;
}
/* Show mobile header on tablet/mobile */
.product-mobile-header {
display: block;
order: 0;
padding: 1rem;
background: #fff;
}
.product-mobile-header .breadcrum {
margin-bottom: 0.5rem;
}
.product-mobile-header .name {
font-size: 1.5rem;
margin: 0;
padding: 0;
border-bottom: none;
}
/* Hide original breadcrumb and name on tablet/mobile */
.product-wrapper > .breadcrum,
.product-wrapper > .name {
display: none;
}
/* Reorder product page layout */
.product.content-wrapper {
display: flex;
flex-direction: column;
padding: 0;
margin: 0;
gap: 0;
max-width: 100%;
border-radius: 0;
box-shadow: none;
}
/* Full width carousel */
.carousel-container,
.product-imgs {
order: 1;
width: 100%;
padding: 0;
}
.carousel-main {
border-radius: 0;
padding: 0;
min-height: auto;
max-height: 60vh;
}
.carousel-main img {
max-width: 100%;
max-height: 60vh;
width: 100%;
border-radius: 0;
}
.carousel-arrow {
padding: 0.5rem 0.75rem;
font-size: 1.25rem;
}
.carousel-arrow.left { left: 5px; }
.carousel-arrow.right { right: 5px; }
/* Thumbnails */
.carousel-thumbnails {
margin-top: 10px;
padding: 10px;
justify-content: flex-start;
gap: 8px;
}
.product-img-small {
width: 55px;
height: 55px;
}
/* Product wrapper */
.product-wrapper {
order: 2;
padding: 1rem;
}
/* Breadcrumb - smaller on tablet/mobile */
.breadcrum {
font-size: 0.8rem;
margin-bottom: 0.5rem;
}
/* Always sticky add to basket on tablet/mobile */
.add-to-basket-sticky {
position: fixed !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
width: 100% !important;
z-index: 1000 !important;
border-radius: 0 !important;
margin: 0 !important;
padding: 1rem !important;
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.15) !important;
}
/* Add padding at bottom for sticky button */
.product.content-wrapper {
padding-bottom: 70px;
}
/* Prices/stock spacing */
.product-wrapper .prices,
.product-wrapper .stock {
margin-bottom: 0.75rem;
}
}
/* Extra small screens */
@media (max-width: 480px) {
.carousel-main img {
max-height: 50vh;
}
.product-img-small {
width: 50px;
height: 50px;
}
.carousel-arrow {
padding: 0.4rem 0.6rem;
font-size: 1rem;
}
}
</style>';
}
$view .= '
<script>
<script>
// Push viewContent event to dataLayer
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
"event": "viewContent",
"ecommerce": {
"detail": {
"products": [{
"id": "' . $product['rowID'] . '",
"name": "' . addslashes(${$product['productname']} ?? $product['productname']) . '",
"price": "' . $product['price'] . '",
"category": "' . ($product['category_name'] ?? '') . '"
}]
}
},
"content_type": "product",
"content_ids": ["' . $product['rowID'] . '"],
"content_name": "' . addslashes(${$product['productname']} ?? $product['productname']) . '",
"value": "' . $product['price'] . '",
"currency": "EUR"
});
// Pre-select option from URL
(function() {
//Read urlstring
const queryString = window.location.href;
const option_id = queryString.substring(queryString.lastIndexOf(\'/\') + 1);
@@ -308,20 +667,21 @@ $view .= '
//Check for option_id
if (option_id != url_slug){
document.getElementById(option_id).checked = true;
const optionElement = document.getElementById(option_id);
if (optionElement) {
optionElement.checked = true;
}
} else {
// Get all radio buttons
const radioButtons = document.querySelectorAll(\'.picture_select_label input[type="radio"]\');
// Select the first radio button if any exist
if (radioButtons.length > 0) {
radioButtons[0].checked = true;
radioButtons[0].checked = true;
}
}
</script>';
}
})();
</script>';
$view .= template_footer();

View File

@@ -9,37 +9,66 @@ $num_products_on_each_page = 25;
//GET Details from URL
$GET_VALUES = urlGETdetails($_GET) ?? '';
//Get all the categories from the database
$categories = ioAPIv2('/v2/categories/','',$clientsecret);
$categories = json_decode($categories,true);
//Get all the categories from cached data
$categories = $GLOBALS['cached_categories'];
//IF CATEGORY IS RECEIVED ONLY GET RELATED PRODUCTS
$url_input = '';
if(isset($_GET['category']) && !isset($_POST['category'])){
$url_input = 'category='.$_GET['category'];
// Deduplicate categories by rowID (since categories repeat for each product)
$unique_categories = [];
foreach ($categories as $cat) {
$unique_categories[$cat['rowID']] = $cat;
}
$categories = array_values($unique_categories);
//Get all products from cached data
$products = $GLOBALS['cached_catalog'];
// Build product-to-categories mapping for filtering
$product_categories_map = [];
foreach ($GLOBALS['cached_categories'] as $cat) {
if (isset($cat['product_id'])) {
$product_id = $cat['product_id'];
if (!isset($product_categories_map[$product_id])) {
$product_categories_map[$product_id] = [];
}
// Only add categories that have status=1 and filter=1
if (isset($cat['status']) && $cat['status'] == 1) {
$product_categories_map[$product_id][] = $cat['rowID'];
}
}
}
if (isset($_POST['category'])){
$filter_input = '';
// Add categories array to each product for JavaScript filtering
foreach ($products as &$product) {
$product_id = $product['rowID'];
$product['category_ids'] = isset($product_categories_map[$product_id])
? array_unique($product_categories_map[$product_id])
: [];
}
unset($product);
foreach (array_keys($_POST['category']) as $cat_filter){
$filter_input .= $cat_filter.',';
}
if ($url_input != ''){
$url_input = $url_input.','.substr($filter_input,0, -1);
} else {
$url_input = 'category='.substr($filter_input,0, -1);
}
}
//GET CATALOG DATA
$products = ioAPIv2('/v2/catalog/'.$url_input,'',$clientsecret);
$products = json_decode($products,true);
$total_products = count($products);
// Get URL category filter if present
$url_category_filter = isset($_GET['category']) ? explode(',', $_GET['category']) : [];
// Expand parent categories to include all their children
$expanded_filters = [];
foreach ($url_category_filter as $cat_id) {
$expanded_filters[] = $cat_id;
// Find all children of this category
foreach ($unique_categories as $cat) {
if ($cat['parent_id'] == $cat_id && $cat['status'] == 1 && $cat['filter'] == 1) {
$expanded_filters[] = $cat['rowID'];
}
}
}
$url_category_filter = array_unique($expanded_filters);
// Debug: log what category was received
if (debug && !empty($url_category_filter)) {
debuglog('URL category filter (expanded): ' . implode(',', $url_category_filter));
}
//SORT BY NAME
usort($products, function($a, $b) {
return strcmp($a['productname'], $b['productname']);
@@ -50,7 +79,7 @@ $view = template_header($products_text,'');
$view .= '
<!-- Hero Section -->
<section class="hero" style="background-image:url('.base_url.featured_store_image.');">
<section class="hero hero-products" style="background-image:url('.base_url.featured_store_image.');">
<div class="hero-content">
<h1>'.$h1_content_top.'</h1>
</div>
@@ -64,7 +93,7 @@ $view .= '
<div class="filters-products-container">
<div class="filters" id="filters">
<form action="" method="post">';
<div class="filter-container">';
if (count($categories) > 0){
//BUILD UP FILTERS BASED ON CATEGORY ASSIGNMENTS
@@ -77,10 +106,11 @@ $view .= '
//Iterate through categories for subfilters
foreach ($categories as $subfilter){
if ($filters['rowID'] == $subfilter['parent_id'] && $subfilter['status'] == 1 && $subfilter['filter'] == 1){
$checked = in_array($subfilter['rowID'], $url_category_filter) ? 'checked' : '';
$view .= '
<div class="filter-option">
<input type="checkbox" id="'.$subfilter['name'].'" name="category['.$subfilter['rowID'].']">
<label for="'.$subfilter['name'].'">'.(${$subfilter['name']} ?? $subfilter['name']).'</label>
<input type="checkbox" class="filter-checkbox" id="cat_'.$subfilter['rowID'].'" data-category="'.$subfilter['rowID'].'" '.$checked.'>
<label for="cat_'.$subfilter['rowID'].'">'.(${$subfilter['name']} ?? $subfilter['name']).'</label>
</div>';
}
}
@@ -90,10 +120,10 @@ $view .= '
}
$view .= '
<div class="filter-option">
<input type="submit" value="'.($btn_filter ?? 'Filter').'" class="btn" >
<button type="button" id="clearFilters" class="btn" style="display:none;">'.($btn_clear_filters ?? 'Clear Filters').'</button>
</div>';
}
$view .= '</form>
$view .= '</div>
</div>
<div class="products">
<div class="product-grid">';
@@ -105,7 +135,7 @@ $view .= '</form>
$view .= '
<div class="product-card">
<div class="product-card" data-categories="'.implode(',', $product['category_ids']).'" data-product-id="'.$product['rowID'].'">
<a href="'.url('index.php?page=product&rowID=' . ($product['url_slug'] ? ($product['url_slug'] ) : $product['rowID'])).(!empty($product['main_option_for_display']) ? '/'.$product['main_option_for_display']:'').'" id="'.$product['rowID'].'A" class="product">
<img src="'.img_url.$product['full_path'].'" id="'.$product['rowID'].'" width="" height="250" alt="'.(${$product['productname']} ?? $product['productname']).'">
</a>';
@@ -223,7 +253,7 @@ $view .= '
}
</script>
<script>
// Simple filter toggle for mobile
// Filter toggle for mobile
const filterToggle = document.getElementById(\'filterToggle\');
const filters = document.getElementById(\'filters\');
@@ -231,6 +261,104 @@ $view .= '
filters.classList.toggle(\'show\');
filterToggle.textContent = filters.classList.contains(\'show\') ? \'Hide Filters\' : \'Show Filters\';
});
// Client-side product filtering
const filterCheckboxes = document.querySelectorAll(\'.filter-checkbox\');
const productCards = document.querySelectorAll(\'.product-card\');
const clearFiltersBtn = document.getElementById(\'clearFilters\');
let activeFilters = new Set();
console.log(\'Filter system initialized\');
console.log(\'Total checkboxes:\', filterCheckboxes.length);
console.log(\'Total product cards:\', productCards.length);
// Debug: Log all product categories
productCards.forEach((card, idx) => {
if (idx < 3) {
console.log(\'Product\', idx, \'categories:\', card.getAttribute(\'data-categories\'));
}
});
// Debug: Log all filter categories
const filterCategories = [];
filterCheckboxes.forEach(checkbox => {
filterCategories.push(checkbox.getAttribute(\'data-category\'));
});
console.log(\'Filter categories:\', filterCategories);
// Initialize filters from pre-checked checkboxes (from URL params)
filterCheckboxes.forEach(checkbox => {
if (checkbox.checked) {
const category = checkbox.getAttribute(\'data-category\');
activeFilters.add(category);
}
});
// Run initial filter if there are pre-selected categories
if (activeFilters.size > 0) {
filterProducts();
}
// Filter products based on selected categories
function filterProducts() {
let visibleCount = 0;
console.log(\'Active filters:\', Array.from(activeFilters));
productCards.forEach(card => {
const productCategoriesStr = card.getAttribute(\'data-categories\');
const productCategories = productCategoriesStr ? productCategoriesStr.split(\',\') : [];
// If no filters active, show all products
if (activeFilters.size === 0) {
card.style.display = \'\';
visibleCount++;
} else {
// Show product if ANY of its categories match the active filters
const hasMatch = productCategories.some(cat => activeFilters.has(cat));
if (hasMatch) {
card.style.display = \'\';
visibleCount++;
} else {
card.style.display = \'none\';
}
}
});
// Show/hide clear button
if (clearFiltersBtn) {
clearFiltersBtn.style.display = activeFilters.size > 0 ? \'inline-block\' : \'none\';
}
console.log(\'Showing \' + visibleCount + \' of \' + productCards.length + \' products\');
}
// Add event listeners to checkboxes
filterCheckboxes.forEach(checkbox => {
checkbox.addEventListener(\'change\', function() {
const category = this.getAttribute(\'data-category\');
console.log(\'Checkbox changed:\', category, \'checked:\', this.checked);
if (this.checked) {
activeFilters.add(category);
} else {
activeFilters.delete(category);
}
filterProducts();
});
});
// Clear all filters
if (clearFiltersBtn) {
clearFiltersBtn.addEventListener(\'click\', () => {
filterCheckboxes.forEach(checkbox => {
checkbox.checked = false;
});
activeFilters.clear();
filterProducts();
});
}
</script>
';

263
script.js
View File

@@ -1,17 +1,193 @@
if (document.querySelector('.product-img-small')) {
let imgs = document.querySelectorAll('.product-img-small img');
let mainImg = document.querySelector('.product-img-large img');
// Initialize dataLayer for Google Tag Manager
window.dataLayer = window.dataLayer || [];
imgs.forEach(img => {
img.onclick = () => {
// Update main image
document.querySelector('.product-img-large img').src = img.src;
// Update selection
imgs.forEach(i => i.parentElement.classList.remove('selected'));
img.parentElement.classList.add('selected');
};
// Push virtual page view event on page load
window.dataLayer.push({
'event': 'virtualPageview',
'pagePath': window.location.pathname + window.location.search,
'pageTitle': document.title
});
// --- Product Carousel Logic ---
document.addEventListener('DOMContentLoaded', function initProductCarousel() {
const carouselMain = document.querySelector('.carousel-main');
if (!carouselMain) return;
const mainImg = carouselMain.querySelector('img');
const thumbs = Array.from(document.querySelectorAll('.carousel-thumbnails .product-img-small'));
const leftArrow = document.querySelector('.carousel-arrow.left');
const rightArrow = document.querySelector('.carousel-arrow.right');
if (!mainImg || thumbs.length === 0) return;
let current = thumbs.findIndex(t => t.classList.contains('selected'));
if (current === -1) current = 0;
let isAnimating = false;
function updateCarousel(idx, smooth = true) {
if (isAnimating || thumbs.length === 0) return;
// Infinite loop logic
if (idx < 0) idx = thumbs.length - 1;
if (idx >= thumbs.length) idx = 0;
// Animate transition
if (smooth) {
isAnimating = true;
mainImg.style.opacity = '0.5';
}
// Update selected thumbnail
thumbs.forEach(t => t.classList.remove('selected'));
thumbs[idx].classList.add('selected');
// Update main image
const newSrc = thumbs[idx].querySelector('img').src;
if (smooth) {
setTimeout(() => {
mainImg.src = newSrc;
mainImg.style.opacity = '1';
isAnimating = false;
}, 150);
} else {
mainImg.src = newSrc;
}
current = idx;
// Scroll thumbnail into view (centered)
const thumbContainer = document.querySelector('.carousel-thumbnails');
if (thumbContainer) {
const thumbElement = thumbs[idx];
const containerRect = thumbContainer.getBoundingClientRect();
const thumbRect = thumbElement.getBoundingClientRect();
const scrollLeft = thumbElement.offsetLeft - (containerRect.width / 2) + (thumbRect.width / 2);
thumbContainer.scrollTo({ left: scrollLeft, behavior: 'smooth' });
}
}
// Arrow click handlers
if (leftArrow) {
leftArrow.addEventListener('click', (e) => {
e.preventDefault();
updateCarousel(current - 1);
});
}
if (rightArrow) {
rightArrow.addEventListener('click', (e) => {
e.preventDefault();
updateCarousel(current + 1);
});
}
// Thumbnail click handlers
thumbs.forEach((thumb, idx) => {
thumb.addEventListener('click', () => updateCarousel(idx));
});
}
// Swipe support for touch devices
let touchStartX = null;
carouselMain.addEventListener('touchstart', (e) => {
touchStartX = e.touches[0].clientX;
}, { passive: true });
carouselMain.addEventListener('touchend', (e) => {
if (touchStartX === null) return;
const endX = e.changedTouches[0].clientX;
const diffX = endX - touchStartX;
// Require minimum swipe distance
if (Math.abs(diffX) > 50) {
if (diffX > 0) {
updateCarousel(current - 1); // Swipe right = previous
} else {
updateCarousel(current + 1); // Swipe left = next
}
}
touchStartX = null;
}, { passive: true });
// Keyboard navigation
document.addEventListener('keydown', (e) => {
// Only if carousel is visible in viewport
const rect = carouselMain.getBoundingClientRect();
const inViewport = rect.top < window.innerHeight && rect.bottom > 0;
if (!inViewport) return;
if (e.key === 'ArrowLeft') {
e.preventDefault();
updateCarousel(current - 1);
} else if (e.key === 'ArrowRight') {
e.preventDefault();
updateCarousel(current + 1);
}
});
// Initialize first thumbnail as selected
updateCarousel(current, false);
});
// --- Sticky Add to Basket Button ---
(function handleStickyButton() {
const btn = document.querySelector('.add-to-basket-sticky');
if (!btn) return;
// Store original position after page load
let originalBottom = null;
let isInitialized = false;
function initPosition() {
const rect = btn.getBoundingClientRect();
originalBottom = window.scrollY + rect.bottom;
isInitialized = true;
checkSticky();
}
function checkSticky() {
if (!isInitialized) return;
// On tablet/mobile (992px and below), always keep sticky
if (window.innerWidth <= 992) {
btn.classList.add('is-sticky');
return;
}
// On desktop: sticky while user hasn't scrolled past the button's original position
const viewportBottom = window.scrollY + window.innerHeight;
if (viewportBottom < originalBottom) {
// User hasn't scrolled enough to see the button naturally
btn.classList.add('is-sticky');
} else {
// User has scrolled past where the button would naturally be
btn.classList.remove('is-sticky');
}
}
function handleResize() {
// Recalculate position on resize
btn.classList.remove('is-sticky');
setTimeout(() => {
initPosition();
}, 100);
}
// Initialize after DOM is ready and images are loaded
if (document.readyState === 'complete') {
initPosition();
} else {
window.addEventListener('load', initPosition);
}
window.addEventListener('scroll', checkSticky, { passive: true });
window.addEventListener('resize', handleResize, { passive: true });
})();
if (document.querySelector('.product #product-form')) {
let updatePrice = () => {
let price = parseFloat(document.querySelector('.product .price').dataset.price);
@@ -45,6 +221,40 @@ if (document.querySelector('.product #product-form')) {
};
document.querySelectorAll('.product #product-form .option').forEach(ele => ele.onchange = () => updatePrice());
updatePrice();
// Add to cart event
document.querySelector('.product #product-form').addEventListener('submit', function(e) {
e.preventDefault(); // Prevent immediate submission
let productId = document.querySelector('input[name="product[product]"]').value;
let quantity = parseInt(document.querySelector('input[name="product[quantity]"]').value);
let productName = document.querySelector('.product .name').textContent;
let price = parseFloat(document.querySelector('.product .price').dataset.price);
window.dataLayer.push({
'event': 'addToCart',
'ecommerce': {
'add': {
'products': [{
'id': productId,
'name': productName,
'price': price,
'quantity': quantity
}]
}
},
'content_type': 'product',
'content_ids': [productId],
'content_name': productName,
'value': price * quantity,
'currency': 'EUR'
});
// Submit form after a short delay
setTimeout(() => {
e.target.submit();
}, 100);
});
}
if (document.querySelector('.products-form')) {
let products_form_submit = () => {
@@ -74,6 +284,11 @@ if (document.querySelector('.cart .ajax-update')) {
document.querySelectorAll('.product-total').forEach((e,i) => {
e.innerHTML = doc.querySelectorAll('.product-total')[i].innerHTML;
});
// Push cart update event
window.dataLayer.push({
'event': 'updateCart'
});
});
};
});
@@ -94,6 +309,12 @@ const checkoutHandler = () => {
document.querySelector('.total').innerHTML = doc.querySelector('.total').innerHTML;
document.querySelector('.discount-code .result').innerHTML = doc.querySelector('.discount-code .result').innerHTML;
document.querySelector('.shipping-methods-container').innerHTML = doc.querySelector('.shipping-methods-container').innerHTML;
// Push checkout update event
window.dataLayer.push({
'event': 'checkoutUpdate'
});
checkoutHandler();
});
};
@@ -130,6 +351,13 @@ function update(id_large, IMG_large, option_id, price){
function updateOption(id_large, IMG_large){
//change picture
document.getElementById(id_large).src = IMG_large;
// Update the first thumbnail to match the new main image
let firstThumbnail = document.querySelector('.product-img-small img');
if (firstThumbnail) {
firstThumbnail.src = IMG_large;
firstThumbnail.parentElement.classList.add('selected');
}
}
@@ -217,12 +445,5 @@ function initializeCarousels() {
});
}
// Initialize carousels when DOM is loaded
document.addEventListener('DOMContentLoaded', initializeCarousels);
// Also initialize if DOM is already loaded
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeCarousels);
} else {
initializeCarousels();
}
// Only initialize carousels once DOM is loaded
// (No duplicate or stray HTML allowed)

View File

@@ -87,7 +87,7 @@ try {
$invoice_language = 'US'; // Default fallback
}
list($data,$customer_email,$order_id) = generateInvoice($invoice_cust,$orderId,$invoice_language);
list($data,$invoice_customer_email,$order_id) = generateInvoice($invoice_cust,$orderId,$invoice_language);
//CREATE PDF
$dompdf->loadHtml($data);
@@ -102,7 +102,7 @@ try {
//++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Send to PHPMailer
//++++++++++++++++++++++++++++++++++++++++++++++++++++++
send_mail_by_PHPMailer($customer_email, $subject, $data, $attachment, $subject);
send_mail_by_PHPMailer($invoice_customer_email, $subject, $data, $attachment, $subject);
if(invoice_bookkeeping){
send_mail_by_PHPMailer(email_bookkeeping, $subject, $data, $attachment, $subject);

View File

@@ -82,7 +82,7 @@ if($token !=''){
$invoice_language = 'US'; // Default fallback
}
list($data,$customer_email,$order_id) = generateInvoice($invoice_cust,$orderId,$invoice_language);
list($data,$invoice_customer_email,$order_id) = generateInvoice($invoice_cust,$orderId,$invoice_language);
//CREATE PDF
$dompdf->loadHtml($data);
@@ -97,7 +97,7 @@ if($token !=''){
//++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Send to PHPMailer
//++++++++++++++++++++++++++++++++++++++++++++++++++++++
send_mail_by_PHPMailer($customer_email, $subject, $data, $attachment, $subject);
send_mail_by_PHPMailer($invoice_customer_email, $subject, $data, $attachment, $subject);
if(invoice_bookkeeping){
send_mail_by_PHPMailer(email_bookkeeping, $subject, $data, $attachment, $subject);