diff --git a/composer.json b/composer.json
index 33586ab..c38cbe7 100644
--- a/composer.json
+++ b/composer.json
@@ -41,6 +41,7 @@
"laravel/tinker": "^2.7",
"laravel/ui": "^4.0",
"phpmailer/phpmailer": "^6.9",
+ "phpoffice/phpspreadsheet": "^4.1",
"proengsoft/laravel-jsvalidation": "^4.0.0",
"spatie/laravel-query-builder": "^5.0",
"vanguardapp/activity-log": "^6.0",
diff --git a/composer.lock b/composer.lock
index 2329f65..8a6ece5 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "3d85faea6470d55b627da7cc0e8c9a67",
+ "content-hash": "a7749f3b43e37d8fb607bcccd227f5ee",
"packages": [
{
"name": "akaunting/laravel-setting",
@@ -320,6 +320,85 @@
],
"time": "2024-02-09T16:56:22+00:00"
},
+ {
+ "name": "composer/pcre",
+ "version": "3.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/pcre.git",
+ "reference": "ea4ab6f9580a4fd221e0418f2c357cdd39102a90"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/pcre/zipball/ea4ab6f9580a4fd221e0418f2c357cdd39102a90",
+ "reference": "ea4ab6f9580a4fd221e0418f2c357cdd39102a90",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4 || ^8.0"
+ },
+ "conflict": {
+ "phpstan/phpstan": "<1.11.8"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.11.8",
+ "phpstan/phpstan-strict-rules": "^1.1",
+ "phpunit/phpunit": "^8 || ^9"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.x-dev"
+ },
+ "phpstan": {
+ "includes": [
+ "extension.neon"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\Pcre\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "PCRE wrapping library that offers type-safe preg_* replacements.",
+ "keywords": [
+ "PCRE",
+ "preg",
+ "regex",
+ "regular expression"
+ ],
+ "support": {
+ "issues": "https://github.com/composer/pcre/issues",
+ "source": "https://github.com/composer/pcre/tree/3.2.0"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-07-25T09:36:02+00:00"
+ },
{
"name": "dasprid/enum",
"version": "1.0.5",
@@ -2740,6 +2819,191 @@
},
"time": "2022-04-15T14:02:14+00:00"
},
+ {
+ "name": "maennchen/zipstream-php",
+ "version": "3.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/maennchen/ZipStream-PHP.git",
+ "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/aeadcf5c412332eb426c0f9b4485f6accba2a99f",
+ "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "ext-zlib": "*",
+ "php-64bit": "^8.2"
+ },
+ "require-dev": {
+ "brianium/paratest": "^7.7",
+ "ext-zip": "*",
+ "friendsofphp/php-cs-fixer": "^3.16",
+ "guzzlehttp/guzzle": "^7.5",
+ "mikey179/vfsstream": "^1.6",
+ "php-coveralls/php-coveralls": "^2.5",
+ "phpunit/phpunit": "^11.0",
+ "vimeo/psalm": "^6.0"
+ },
+ "suggest": {
+ "guzzlehttp/psr7": "^2.4",
+ "psr/http-message": "^2.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "ZipStream\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Paul Duncan",
+ "email": "pabs@pablotron.org"
+ },
+ {
+ "name": "Jonatan Männchen",
+ "email": "jonatan@maennchen.ch"
+ },
+ {
+ "name": "Jesse Donat",
+ "email": "donatj@gmail.com"
+ },
+ {
+ "name": "András Kolesár",
+ "email": "kolesar@kolesar.hu"
+ }
+ ],
+ "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
+ "keywords": [
+ "stream",
+ "zip"
+ ],
+ "support": {
+ "issues": "https://github.com/maennchen/ZipStream-PHP/issues",
+ "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/maennchen",
+ "type": "github"
+ }
+ ],
+ "time": "2025-01-27T12:07:53+00:00"
+ },
+ {
+ "name": "markbaker/complex",
+ "version": "3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/MarkBaker/PHPComplex.git",
+ "reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
+ "reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "require-dev": {
+ "dealerdirect/phpcodesniffer-composer-installer": "dev-master",
+ "phpcompatibility/php-compatibility": "^9.3",
+ "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
+ "squizlabs/php_codesniffer": "^3.7"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Complex\\": "classes/src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mark Baker",
+ "email": "mark@lange.demon.co.uk"
+ }
+ ],
+ "description": "PHP Class for working with complex numbers",
+ "homepage": "https://github.com/MarkBaker/PHPComplex",
+ "keywords": [
+ "complex",
+ "mathematics"
+ ],
+ "support": {
+ "issues": "https://github.com/MarkBaker/PHPComplex/issues",
+ "source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.2"
+ },
+ "time": "2022-12-06T16:21:08+00:00"
+ },
+ {
+ "name": "markbaker/matrix",
+ "version": "3.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/MarkBaker/PHPMatrix.git",
+ "reference": "728434227fe21be27ff6d86621a1b13107a2562c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/728434227fe21be27ff6d86621a1b13107a2562c",
+ "reference": "728434227fe21be27ff6d86621a1b13107a2562c",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0"
+ },
+ "require-dev": {
+ "dealerdirect/phpcodesniffer-composer-installer": "dev-master",
+ "phpcompatibility/php-compatibility": "^9.3",
+ "phpdocumentor/phpdocumentor": "2.*",
+ "phploc/phploc": "^4.0",
+ "phpmd/phpmd": "2.*",
+ "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
+ "sebastian/phpcpd": "^4.0",
+ "squizlabs/php_codesniffer": "^3.7"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Matrix\\": "classes/src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mark Baker",
+ "email": "mark@demon-angel.eu"
+ }
+ ],
+ "description": "PHP Class for working with matrices",
+ "homepage": "https://github.com/MarkBaker/PHPMatrix",
+ "keywords": [
+ "mathematics",
+ "matrix",
+ "vector"
+ ],
+ "support": {
+ "issues": "https://github.com/MarkBaker/PHPMatrix/issues",
+ "source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.1"
+ },
+ "time": "2022-12-02T22:17:43+00:00"
+ },
{
"name": "mobiledetect/mobiledetectlib",
"version": "2.8.45",
@@ -3501,6 +3765,111 @@
],
"time": "2024-11-24T18:04:13+00:00"
},
+ {
+ "name": "phpoffice/phpspreadsheet",
+ "version": "4.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
+ "reference": "6ff18c3a8df3a945492f75ce455d77f7ad55dd5c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/6ff18c3a8df3a945492f75ce455d77f7ad55dd5c",
+ "reference": "6ff18c3a8df3a945492f75ce455d77f7ad55dd5c",
+ "shasum": ""
+ },
+ "require": {
+ "composer/pcre": "^1||^2||^3",
+ "ext-ctype": "*",
+ "ext-dom": "*",
+ "ext-fileinfo": "*",
+ "ext-gd": "*",
+ "ext-iconv": "*",
+ "ext-libxml": "*",
+ "ext-mbstring": "*",
+ "ext-simplexml": "*",
+ "ext-xml": "*",
+ "ext-xmlreader": "*",
+ "ext-xmlwriter": "*",
+ "ext-zip": "*",
+ "ext-zlib": "*",
+ "maennchen/zipstream-php": "^2.1 || ^3.0",
+ "markbaker/complex": "^3.0",
+ "markbaker/matrix": "^3.0",
+ "php": "^8.1",
+ "psr/http-client": "^1.0",
+ "psr/http-factory": "^1.0",
+ "psr/simple-cache": "^1.0 || ^2.0 || ^3.0"
+ },
+ "require-dev": {
+ "dealerdirect/phpcodesniffer-composer-installer": "dev-main",
+ "dompdf/dompdf": "^2.0 || ^3.0",
+ "friendsofphp/php-cs-fixer": "^3.2",
+ "mitoteam/jpgraph": "^10.3",
+ "mpdf/mpdf": "^8.1.1",
+ "phpcompatibility/php-compatibility": "^9.3",
+ "phpstan/phpstan": "^1.1",
+ "phpstan/phpstan-phpunit": "^1.0",
+ "phpunit/phpunit": "^10.5",
+ "squizlabs/php_codesniffer": "^3.7",
+ "tecnickcom/tcpdf": "^6.5"
+ },
+ "suggest": {
+ "dompdf/dompdf": "Option for rendering PDF with PDF Writer",
+ "ext-intl": "PHP Internationalization Functions",
+ "mitoteam/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers",
+ "mpdf/mpdf": "Option for rendering PDF with PDF Writer",
+ "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Maarten Balliauw",
+ "homepage": "https://blog.maartenballiauw.be"
+ },
+ {
+ "name": "Mark Baker",
+ "homepage": "https://markbakeruk.net"
+ },
+ {
+ "name": "Franck Lefevre",
+ "homepage": "https://rootslabs.net"
+ },
+ {
+ "name": "Erik Tilt"
+ },
+ {
+ "name": "Adrien Crivelli"
+ }
+ ],
+ "description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
+ "homepage": "https://github.com/PHPOffice/PhpSpreadsheet",
+ "keywords": [
+ "OpenXML",
+ "excel",
+ "gnumeric",
+ "ods",
+ "php",
+ "spreadsheet",
+ "xls",
+ "xlsx"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues",
+ "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/4.1.0"
+ },
+ "time": "2025-03-02T06:52:24+00:00"
+ },
{
"name": "phpoption/phpoption",
"version": "1.9.3",
@@ -7873,85 +8242,6 @@
],
"time": "2024-06-12T14:13:04+00:00"
},
- {
- "name": "composer/pcre",
- "version": "3.2.0",
- "source": {
- "type": "git",
- "url": "https://github.com/composer/pcre.git",
- "reference": "ea4ab6f9580a4fd221e0418f2c357cdd39102a90"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/composer/pcre/zipball/ea4ab6f9580a4fd221e0418f2c357cdd39102a90",
- "reference": "ea4ab6f9580a4fd221e0418f2c357cdd39102a90",
- "shasum": ""
- },
- "require": {
- "php": "^7.4 || ^8.0"
- },
- "conflict": {
- "phpstan/phpstan": "<1.11.8"
- },
- "require-dev": {
- "phpstan/phpstan": "^1.11.8",
- "phpstan/phpstan-strict-rules": "^1.1",
- "phpunit/phpunit": "^8 || ^9"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "3.x-dev"
- },
- "phpstan": {
- "includes": [
- "extension.neon"
- ]
- }
- },
- "autoload": {
- "psr-4": {
- "Composer\\Pcre\\": "src"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Jordi Boggiano",
- "email": "j.boggiano@seld.be",
- "homepage": "http://seld.be"
- }
- ],
- "description": "PCRE wrapping library that offers type-safe preg_* replacements.",
- "keywords": [
- "PCRE",
- "preg",
- "regex",
- "regular expression"
- ],
- "support": {
- "issues": "https://github.com/composer/pcre/issues",
- "source": "https://github.com/composer/pcre/tree/3.2.0"
- },
- "funding": [
- {
- "url": "https://packagist.com",
- "type": "custom"
- },
- {
- "url": "https://github.com/composer",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/composer/composer",
- "type": "tidelift"
- }
- ],
- "time": "2024-07-25T09:36:02+00:00"
- },
{
"name": "doctrine/deprecations",
"version": "1.1.3",
diff --git a/public/userarea/edit_template_xls.php b/public/userarea/edit_template_xls.php
index eb5bdb3..80fb0d1 100644
--- a/public/userarea/edit_template_xls.php
+++ b/public/userarea/edit_template_xls.php
@@ -19,30 +19,56 @@ if (!$template) {
header("Location: template_dashboard.php?status=error&message=" . urlencode("Template not found"));
exit;
}
+
+// Debug del JSON
+$clientSpecificFieldsJson = $template['client_specific_fields'] ?? '{}';
+error_log("Raw client_specific_fields JSON: " . $clientSpecificFieldsJson);
+
+$clientSpecificFields = json_decode($clientSpecificFieldsJson, true);
+if (json_last_error() !== JSON_ERROR_NONE) {
+ error_log("JSON decode error: " . json_last_error_msg());
+ $clientSpecificFields = [];
+} else {
+ error_log("Decoded client_specific_fields: " . print_r($clientSpecificFields, true));
+}
?>
-
-
+
Edit Template = htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?>
-
-
-
-
-
-
@@ -55,8 +81,7 @@ if (!$template) {
4805
+2.5% from last week
-
-
+
@@ -70,8 +95,7 @@ if (!$template) {
$84,245
+5.4% from last week
-
-
+
@@ -85,8 +109,7 @@ if (!$template) {
34.6%
-4.5% from last week
-
-
+
@@ -100,15 +123,12 @@ if (!$template) {
8.4K
+8.4% from last week
-
-
+
-
-
-
+
-
+
+
+
+
+ $fieldData) {
+ if (is_array($fieldData)) {
+ $type = $fieldData['type'] ?? 'text';
+ $possibleValues = implode(', ', $fieldData['possible_values'] ?? []);
+ $isRequired = isset($fieldData['is_required']) && $fieldData['is_required'] ? '1' : '0';
+ $exportColumnName = $fieldData['export_column_name'] ?? '';
+ $defaultValue = $fieldData['default_value'] ?? '';
+ error_log("Rendering field: $fieldName, type: $type, possible_values: $possibleValues, required: $isRequired, export: $exportColumnName, default: $defaultValue");
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Cancel
-
@@ -170,57 +251,249 @@ if (!$template) {
-
-
-
+
+
diff --git a/public/userarea/import_dashboard.php b/public/userarea/import_dashboard.php
new file mode 100644
index 0000000..b3c0ad0
--- /dev/null
+++ b/public/userarea/import_dashboard.php
@@ -0,0 +1,134 @@
+
+
+
+
+
+
+
+
+
+ Template Buttons - = htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/public/userarea/import_xls.php b/public/userarea/import_xls.php
new file mode 100644
index 0000000..e519fde
--- /dev/null
+++ b/public/userarea/import_xls.php
@@ -0,0 +1,316 @@
+getConnection();
+$stmt = $pdo->prepare("SELECT * FROM excel_templates WHERE id = ?");
+$stmt->execute([$id]);
+$template = $stmt->fetch(PDO::FETCH_ASSOC);
+
+if (!$template) {
+ header("Location: template_dashboard.php?status=error&message=" . urlencode("Template not found"));
+ exit;
+}
+
+// Debug del template
+error_log("Loaded template: " . print_r($template, true));
+?>
+
+
+
+
+
+
+
+
+
+
+ = htmlspecialchars($template['name']) ?> - = htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/public/userarea/insert_template_xls.php b/public/userarea/insert_template_xls.php
index 9d0db66..d03cdb0 100644
--- a/public/userarea/insert_template_xls.php
+++ b/public/userarea/insert_template_xls.php
@@ -87,15 +87,12 @@
-
-
@@ -125,6 +122,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Cancel
@@ -146,57 +210,200 @@
-
-
diff --git a/public/userarea/insert_template_xlsbck.php b/public/userarea/insert_template_xlsbck.php
new file mode 100644
index 0000000..d03cdb0
--- /dev/null
+++ b/public/userarea/insert_template_xlsbck.php
@@ -0,0 +1,411 @@
+
+
+
+
+
+
+
+
+
+
+
+ Insert XLS Template = htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Total Orders
+
4805
+
+2.5% from last week
+
+
+
+
+
+
+
+
+
+
+
+
+
Total Revenue
+
$84,245
+
+5.4% from last week
+
+
+
+
+
+
+
+
+
+
+
+
+
Bounce Rate
+
34.6%
+
-4.5% from last week
+
+
+
+
+
+
+
+
+
+
+
+
+
Total Customers
+
8.4K
+
+8.4% from last week
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/public/userarea/load_active_templates.php b/public/userarea/load_active_templates.php
new file mode 100644
index 0000000..b0d9fb7
--- /dev/null
+++ b/public/userarea/load_active_templates.php
@@ -0,0 +1,27 @@
+ false, "data" => [], "message" => ""];
+
+try {
+ $db = DBHandlerSelect::getInstance();
+ $pdo = $db->getConnection();
+
+ if (!$pdo) {
+ throw new Exception('Database connection failed.');
+ }
+
+ // Recupera solo i template attivi
+ $stmt = $pdo->query("SELECT id, button_label, button_bg_color, button_text_color, button_size FROM excel_templates WHERE status = 'active'");
+ $templates = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+ $response["success"] = true;
+ $response["data"] = $templates;
+} catch (PDOException $e) {
+ $response["message"] = "Database error: " . $e->getMessage();
+} catch (Exception $e) {
+ $response["message"] = "Error: " . $e->getMessage();
+}
+
+echo json_encode($response);
diff --git a/public/userarea/load_existing_mappings.php b/public/userarea/load_existing_mappings.php
new file mode 100644
index 0000000..14d0bac
--- /dev/null
+++ b/public/userarea/load_existing_mappings.php
@@ -0,0 +1,60 @@
+ false, "message" => "Invalid template ID"]);
+ exit;
+}
+
+$template_id = intval($_GET['template_id']);
+
+try {
+ $db = DBHandlerSelect::getInstance();
+ $pdo = $db->getConnection();
+
+ // 1️⃣ Recuperiamo il nome della tabella target da `excel_templates`
+ $stmt = $pdo->prepare("SELECT target_table FROM excel_templates WHERE id = ?");
+ $stmt->execute([$template_id]);
+ $template = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ if (!$template || empty($template['target_table'])) {
+ echo json_encode(["success" => false, "message" => "Template not found or missing target table"]);
+ exit;
+ }
+
+ $target_table = $template['target_table'];
+
+ // 2️⃣ Recuperiamo le associazioni già esistenti per il template_id
+ $stmt = $pdo->prepare("SELECT excel_column, mysql_column, headerexcel FROM excel_column_mappings WHERE template_id = ?");
+ $stmt->execute([$template_id]);
+ $existing_mappings = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+ // Creiamo gli array delle colonne già mappate
+ $mapped_xls_columns = array_column($existing_mappings, 'excel_column');
+ $mapped_mysql_columns = array_column($existing_mappings, 'mysql_column'); // CORRETTO PER FILTRARE!
+
+ // 3️⃣ Recuperiamo tutte le colonne disponibili nella tabella MySQL target
+ $stmt = $pdo->prepare("SHOW COLUMNS FROM `$target_table`");
+ $stmt->execute();
+ $table_columns = $stmt->fetchAll(PDO::FETCH_COLUMN);
+
+ // 🔥 FIX: Rimuoviamo le colonne MySQL che sono già state mappate!
+ $remaining_mysql_columns = array_values(array_diff($table_columns, $mapped_mysql_columns));
+
+ // 4️⃣ Se abbiamo salvato gli header XLSX in `headerexcel`, li usiamo per calcolare le colonne XLSX non mappate
+ $headerexcel = !empty($existing_mappings) ? $existing_mappings[0]['headerexcel'] : '';
+ $all_xls_columns = !empty($headerexcel) ? explode(',', $headerexcel) : [];
+ $remaining_xls_columns = array_values(array_diff($all_xls_columns, $mapped_xls_columns));
+
+ // 5️⃣ Invio dei dati al frontend
+ echo json_encode([
+ "success" => true,
+ "mappings" => $existing_mappings,
+ "remaining_xls_columns" => $remaining_xls_columns,
+ "remaining_mysql_columns" => $remaining_mysql_columns // 🔥 ORA LE COLONNE MYSQL SONO FILTRATE!
+ ]);
+} catch (PDOException $e) {
+ echo json_encode(["success" => false, "message" => "Database error: " . $e->getMessage()]);
+}
diff --git a/public/userarea/mapping_template_xls.php b/public/userarea/mapping_template_xls.php
index 764b8c9..c78d415 100644
--- a/public/userarea/mapping_template_xls.php
+++ b/public/userarea/mapping_template_xls.php
@@ -7,10 +7,11 @@ if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
$id = intval($_GET['id']);
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
-$stmt = $pdo->prepare("SELECT name, header_row, start_column, target_table FROM excel_templates WHERE id = ?");
+$stmt = $pdo->prepare("SELECT name, header_row, start_column, target_table, sample_xlsx FROM excel_templates WHERE id = ?");
$stmt->execute([$id]);
$template = $stmt->fetch(PDO::FETCH_ASSOC);
+
if (!$template) {
die("Template not found");
}
@@ -26,6 +27,8 @@ if (!$template) {
Mapping XLS Template = htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?>
+
+
@@ -59,8 +62,20 @@ if (!$template) {
+
+
+
@@ -84,8 +99,9 @@ if (!$template) {
+
@@ -117,8 +133,48 @@ if (!$template) {
diff --git a/public/userarea/process_edit_template_xls.php b/public/userarea/process_edit_template_xls.php
index 2a0e7cc..8bc5dff 100644
--- a/public/userarea/process_edit_template_xls.php
+++ b/public/userarea/process_edit_template_xls.php
@@ -16,21 +16,28 @@ try {
$start_column = trim($_POST['start_column']);
$description = trim($_POST['description'] ?? '');
$target_table = trim($_POST['target_table']);
+ $client_specific_fields = trim($_POST['client_specific_fields'] ?? '{}'); // Recupera il JSON dei campi specifici
// Controllo sui campi obbligatori
if (empty($id) || empty($name) || empty($header_row) || empty($start_column) || empty($target_table)) {
throw new Exception("All fields marked with * are required.");
}
+ // Validazione opzionale del JSON (per sicurezza)
+ $decoded_fields = json_decode($client_specific_fields, true);
+ if (json_last_error() !== JSON_ERROR_NONE && $client_specific_fields !== '{}') {
+ throw new Exception("Invalid JSON format for client-specific fields.");
+ }
+
// Connessione al database
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
- // Aggiorna il database
+ // Aggiorna il database, includendo client_specific_fields
$stmt = $pdo->prepare("UPDATE excel_templates
- SET name = ?, header_row = ?, start_column = ?, description = ?, target_table = ?, updated_at = NOW()
+ SET name = ?, header_row = ?, start_column = ?, description = ?, target_table = ?, client_specific_fields = ?, updated_at = NOW()
WHERE id = ?");
- $stmt->execute([$name, $header_row, $start_column, $description, $target_table, $id]);
+ $stmt->execute([$name, $header_row, $start_column, $description, $target_table, $client_specific_fields, $id]);
if ($stmt->rowCount() > 0) {
$response["success"] = true;
diff --git a/public/userarea/process_import_xls.php b/public/userarea/process_import_xls.php
new file mode 100644
index 0000000..5a2dc3a
--- /dev/null
+++ b/public/userarea/process_import_xls.php
@@ -0,0 +1,93 @@
+ '', 'rows' => [], 'columns' => [], 'template_id' => 0];
+
+try {
+ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['excel_file'])) {
+ $template_id = isset($_POST['template_id']) ? intval($_POST['template_id']) : 0;
+ $header_row = isset($_POST['header_row']) ? intval($_POST['header_row']) : 1;
+ $start_column = isset($_POST['start_column']) ? intval($_POST['start_column']) : 1;
+
+ $file = $_FILES['excel_file'];
+ $fileError = $file['error'];
+
+ if ($fileError === UPLOAD_ERR_OK) {
+ $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file['tmp_name']);
+ $worksheet = $spreadsheet->getActiveSheet();
+ $highestRow = $worksheet->getHighestRow();
+ $highestColumn = $worksheet->getHighestColumn();
+ $highestColumnIndex = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($highestColumn);
+
+ $startRow = max(1, $header_row);
+ $startColumn = max(1, $start_column);
+
+ // Debug dei parametri
+ error_log("Processing - startRow: $startRow, startColumn: $startColumn, highestRow: $highestRow, highestColumn: $highestColumn, highestColumnIndex: $highestColumnIndex");
+
+ // Validazione degli indici
+ if ($startRow > $highestRow) {
+ $response['error'] = "La riga di partenza ($startRow) supera il numero totale di righe ($highestRow).";
+ } elseif ($startColumn > $highestColumnIndex) {
+ $response['error'] = "La colonna di partenza ($startColumn) supera il numero totale di colonne ($highestColumnIndex).";
+ } else {
+ $excelData = [];
+ // Estrai la riga degli header
+ $headerRowData = [];
+ for ($col = $startColumn; $col <= $highestColumnIndex; $col++) {
+ $columnLetter = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col);
+ $cell = $worksheet->getCell($columnLetter . $header_row);
+ $cellValue = $cell ? $cell->getCalculatedValue() : ''; // Usa getCalculatedValue per le formule
+ $headerRowData[] = htmlspecialchars($cellValue ?: '');
+ }
+
+ // Estrai i dati a partire dalla riga successiva
+ for ($row = $startRow + 1; $row <= $highestRow; $row++) {
+ $rowData = [];
+ for ($col = $startColumn; $col <= $highestColumnIndex; $col++) {
+ $columnLetter = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col);
+ $cell = $worksheet->getCell($columnLetter . $row);
+ $cellValue = $cell ? $cell->getCalculatedValue() : ''; // Usa getCalculatedValue per le formule
+ $rowData[] = htmlspecialchars($cellValue ?: '');
+ }
+ if (!empty(array_filter($rowData))) {
+ $excelData[] = $rowData;
+ }
+ }
+
+ // Salva i dati in sessione
+ $_SESSION['excel_data'] = $excelData;
+ $_SESSION['template_id'] = $template_id;
+ $_SESSION['headers'] = $headerRowData; // Salva gli header in sessione
+
+ $response['rows'] = $excelData;
+ $response['columns'] = $headerRowData; // Usa gli header reali
+ $response['template_id'] = $template_id;
+ }
+ } else {
+ $response['error'] = "Errore nell'upload del file: Codice errore $fileError.";
+ }
+ } else {
+ $response['error'] = "Richiesta non valida.";
+ }
+} catch (Exception $e) {
+ $response['error'] = "Errore durante il caricamento del file: " . $e->getMessage();
+ error_log("Exception in process_import_xls.php: " . $e->getMessage());
+}
+
+// Pulisce qualsiasi output indesiderato
+ob_end_clean();
+
+// Invia la risposta JSON
+header('Content-Type: application/json');
+echo json_encode($response);
+exit;
diff --git a/public/userarea/process_insert_template_xls.php b/public/userarea/process_insert_template_xls.php
index 900ab06..1803cf7 100644
--- a/public/userarea/process_insert_template_xls.php
+++ b/public/userarea/process_insert_template_xls.php
@@ -15,6 +15,19 @@ try {
$start_column = trim($_POST['start_column']);
$description = trim($_POST['description'] ?? '');
$target_table = trim($_POST['target_table']);
+ $button_size = trim($_POST['button_size'] ?? 'medium');
+ $button_bg_color = trim($_POST['button_bg_color'] ?? '#007bff');
+ $button_text_color = trim($_POST['button_text_color'] ?? '#ffffff');
+ $button_label = trim($_POST['button_label'] ?? 'Click Me');
+ $status = 'active'; // Default
+
+ // Recupera i client_specific_fields (JSON inviato dal form)
+ $client_specific_fields = trim($_POST['client_specific_fields'] ?? '{}');
+ // Decodifica il JSON per verificare che sia valido (opzionale, per sicurezza)
+ $decoded_fields = json_decode($client_specific_fields, true);
+ if (json_last_error() !== JSON_ERROR_NONE && !empty($client_specific_fields)) {
+ throw new Exception("Invalid JSON format for client-specific fields.");
+ }
// Controllo sui campi obbligatori
if (empty($name) || empty($header_row) || empty($start_column) || empty($target_table)) {
@@ -25,10 +38,11 @@ try {
$db = DBHandlerSelect::getInstance();
$pdo = $db->getConnection();
- // Inserisci nel database
- $stmt = $pdo->prepare("INSERT INTO excel_templates (name, header_row, start_column, description, target_table, created_at, updated_at)
- VALUES (?, ?, ?, ?, ?, NOW(), NOW())");
- $stmt->execute([$name, $header_row, $start_column, $description, $target_table]);
+ // Inserisci nel database, includendo client_specific_fields
+ $stmt = $pdo->prepare("INSERT INTO excel_templates
+ (name, header_row, start_column, description, target_table, button_size, button_bg_color, button_text_color, button_label, status, client_specific_fields, created_at, updated_at)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())");
+ $stmt->execute([$name, $header_row, $start_column, $description, $target_table, $button_size, $button_bg_color, $button_text_color, $button_label, $status, $client_specific_fields]);
if ($stmt->rowCount() > 0) {
$response["success"] = true;
diff --git a/public/userarea/remove_column_mapping.php b/public/userarea/remove_column_mapping.php
new file mode 100644
index 0000000..97316a9
--- /dev/null
+++ b/public/userarea/remove_column_mapping.php
@@ -0,0 +1,62 @@
+getConnection();
+
+$data = json_decode(file_get_contents("php://input"), true);
+
+if (!isset($data['template_id'], $data['excel_column'], $data['mysql_column'], $data['tablename'])) {
+ echo json_encode(["success" => false, "message" => "Missing required fields"]);
+ exit;
+}
+
+// Rimuove l'associazione
+$stmtDelete = $pdo->prepare("
+ DELETE FROM excel_column_mappings
+ WHERE template_id = ? AND excel_column = ? AND mysql_column = ? AND tablename = ?
+");
+$result = $stmtDelete->execute([
+ $data['template_id'],
+ $data['excel_column'],
+ $data['mysql_column'],
+ $data['tablename']
+]);
+
+if (!$result) {
+ echo json_encode(["success" => false, "message" => "Failed to delete mapping"]);
+ exit;
+}
+
+// Dopo la rimozione, aggiorna la lista delle colonne disponibili
+$stmtColumns = $pdo->prepare("SHOW COLUMNS FROM " . $data['tablename']);
+$stmtColumns->execute();
+$all_mysql_columns = array_column($stmtColumns->fetchAll(PDO::FETCH_ASSOC), 'Field');
+
+$stmtHeader = $pdo->prepare("SELECT headerexcel FROM excel_column_mappings WHERE template_id = ? LIMIT 1");
+$stmtHeader->execute([$data['template_id']]);
+$headerRow = $stmtHeader->fetch(PDO::FETCH_ASSOC);
+$xls_headers = isset($headerRow['headerexcel']) ? explode(",", $headerRow['headerexcel']) : [];
+
+// Ricalcola le colonne non associate
+$stmtMappings = $pdo->prepare("SELECT excel_column, mysql_column FROM excel_column_mappings WHERE template_id = ?");
+$stmtMappings->execute([$data['template_id']]);
+$existingMappings = $stmtMappings->fetchAll(PDO::FETCH_ASSOC);
+
+$mapped_xls_columns = array_column($existingMappings, 'excel_column');
+$mapped_mysql_columns = array_column($existingMappings, 'mysql_column');
+
+$remaining_xls_columns = array_diff($xls_headers, $mapped_xls_columns);
+$remaining_mysql_columns = array_diff($all_mysql_columns, $mapped_mysql_columns);
+
+echo json_encode([
+ "success" => true,
+ "remaining_xls_columns" => array_values($remaining_xls_columns),
+ "remaining_mysql_columns" => array_values($remaining_mysql_columns)
+]);
+exit;
diff --git a/public/userarea/save_column_mapping.php b/public/userarea/save_column_mapping.php
new file mode 100644
index 0000000..742e127
--- /dev/null
+++ b/public/userarea/save_column_mapping.php
@@ -0,0 +1,46 @@
+getConnection(); // Ottieni la connessione
+
+$data = json_decode(file_get_contents("php://input"), true);
+
+if (!$data) {
+ echo json_encode(["success" => false, "message" => "Invalid JSON input"]);
+ exit;
+}
+
+if (!isset($data['template_id'], $data['tablename'], $data['excel_column'], $data['mysql_column'])) {
+ echo json_encode(["success" => false, "message" => "Missing required fields"]);
+ exit;
+}
+
+$stmt = $pdo->prepare("
+ INSERT INTO excel_column_mappings
+ (template_id, tablename, excel_column, mysql_column, data_type, is_required, default_value, headerexcel)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
+");
+$result = $stmt->execute([
+ $data['template_id'],
+ $data['tablename'],
+ $data['excel_column'],
+ $data['mysql_column'],
+ $data['data_type'],
+ $data['is_required'],
+ $data['default_value'],
+ $data['headerexcel']
+]);
+
+if (!$result) {
+ echo json_encode(["success" => false, "message" => "Database insert failed"]);
+ exit;
+}
+
+echo json_encode(["success" => true]);
+exit;
diff --git a/public/userarea/templates_dashboard.php b/public/userarea/templates_dashboard.php
index 46d604f..8b896e9 100644
--- a/public/userarea/templates_dashboard.php
+++ b/public/userarea/templates_dashboard.php
@@ -11,6 +11,52 @@
TRF-Project - Template Dashboard
+
@@ -97,49 +143,71 @@
serverSide: false,
ajax: 'load_templates.php',
columns: [{
- data: 'id'
+ data: 'name', // Nome del template
+ title: "Template Name"
},
{
- data: 'name'
- },
- {
- data: 'updated_at',
+ data: 'updated_at', // Ultima modifica, formattata come data leggibile
+ title: "Last Modified",
render: function(data) {
return new Date(data).toLocaleDateString();
}
},
{
- data: 'header_row'
+ data: 'header_row', // Riga degli header
+ title: "Header Row"
},
{
- data: 'start_column'
+ data: 'start_column', // Colonna di partenza
+ title: "Start Column"
},
{
- data: 'description',
+ data: 'description', // Descrizione del template
+ title: "Description",
defaultContent: 'No description'
},
{
- data: 'target_table'
+ data: 'target_table', // Tabella di destinazione
+ title: "Target Table"
},
{
- data: 'id',
+ data: 'status', // Stato con Toggle Switch
+ title: "Status",
orderable: false,
searchable: false,
+ render: function(status, type, row) {
+ let checked = (status === "active") ? "checked" : "";
+ return `
+
+ `;
+ }
+ },
+ {
+ data: 'id', // Azioni: Modifica, Mappatura e Eliminazione
+ orderable: false,
+ searchable: false,
+ title: "Actions",
render: function(data) {
return `
- `;
+
+ `;
}
}
+
+
],
dom: '<"card-header border-bottom p-3"<"d-flex align-items-center"<"card-title mb-0 flex-grow-1"f>>>rt<"card-footer border-top p-3"<"d-flex align-items-center"<"me-auto"l><"d-flex gap-2"ip>>>',
lengthMenu: [10, 25, 50, 100],
@@ -174,6 +242,32 @@
}
});
}
+
+
+ $(document).on("change", ".toggle-status", function() {
+ let templateId = $(this).data("id");
+ let newStatus = $(this).is(":checked") ? "active" : "inactive";
+
+ $.ajax({
+ url: "update_template_status.php",
+ type: "POST",
+ data: {
+ id: templateId,
+ status: newStatus
+ },
+ success: function(response) {
+ if (response.success) {
+ console.log("✅ Status updated successfully.");
+ } else {
+ console.error("❌ Error updating status:", response.message);
+ alert("Error updating status: " + response.message);
+ }
+ },
+ error: function() {
+ console.error("❌ AJAX error.");
+ }
+ });
+ });
diff --git a/public/userarea/update_template_status.php b/public/userarea/update_template_status.php
new file mode 100644
index 0000000..1f31665
--- /dev/null
+++ b/public/userarea/update_template_status.php
@@ -0,0 +1,30 @@
+ false, "message" => ""];
+
+try {
+ if ($_SERVER["REQUEST_METHOD"] !== "POST") {
+ throw new Exception("Invalid request.");
+ }
+
+ $id = intval($_POST['id']);
+ $status = ($_POST['status'] === "active") ? "active" : "inactive";
+
+ $db = DBHandlerSelect::getInstance();
+ $pdo = $db->getConnection();
+
+ $stmt = $pdo->prepare("UPDATE excel_templates SET status = ?, updated_at = NOW() WHERE id = ?");
+ $stmt->execute([$status, $id]);
+
+ if ($stmt->rowCount() > 0) {
+ $response["success"] = true;
+ } else {
+ throw new Exception("Update failed.");
+ }
+} catch (Exception $e) {
+ $response["message"] = $e->getMessage();
+}
+
+echo json_encode($response);
diff --git a/public/userarea/upload_xls_example.php b/public/userarea/upload_xls_example.php
new file mode 100644
index 0000000..04ce32c
--- /dev/null
+++ b/public/userarea/upload_xls_example.php
@@ -0,0 +1,48 @@
+ false, "message" => "Invalid template ID"]);
+ exit;
+}
+
+$template_id = intval($_POST['template_id']);
+
+if (!isset($_FILES['xls_file']) || $_FILES['xls_file']['error'] !== UPLOAD_ERR_OK) {
+ echo json_encode(["success" => false, "message" => "File upload error"]);
+ exit;
+}
+
+$file = $_FILES['xls_file'];
+$originalFilename = pathinfo($file['name'], PATHINFO_FILENAME);
+$extension = pathinfo($file['name'], PATHINFO_EXTENSION);
+
+// Crea il nuovo nome del file: {idtemplate}-{timestamp}-{nomeoriginale}.ext
+$newFilename = $template_id . "-" . time() . "-" . preg_replace("/[^a-zA-Z0-9_-]/", "", $originalFilename) . "." . $extension;
+$uploadDir = __DIR__ . '/xlstemplates/';
+$uploadPath = $uploadDir . $newFilename;
+
+// Assicura che la cartella esista
+if (!is_dir($uploadDir)) {
+ mkdir($uploadDir, 0777, true);
+}
+
+// Salva il file
+if (!move_uploaded_file($file['tmp_name'], $uploadPath)) {
+ echo json_encode(["success" => false, "message" => "Failed to save file"]);
+ exit;
+}
+
+// Aggiorna il database con il nome del file
+try {
+ $db = DBHandlerSelect::getInstance();
+ $pdo = $db->getConnection();
+ $stmt = $pdo->prepare("UPDATE excel_templates SET sample_xlsx = ? WHERE id = ?");
+ $stmt->execute([$newFilename, $template_id]);
+
+ echo json_encode(["success" => true, "filename" => $newFilename, "filepath" => "xlstemplates/" . $newFilename]);
+} catch (PDOException $e) {
+ echo json_encode(["success" => false, "message" => "Database error: " . $e->getMessage()]);
+}
diff --git a/public/userarea/xlstemplates/5-1740733446-row3.xlsx b/public/userarea/xlstemplates/5-1740733446-row3.xlsx
new file mode 100644
index 0000000..4641d24
Binary files /dev/null and b/public/userarea/xlstemplates/5-1740733446-row3.xlsx differ