update document page

This commit is contained in:
Claudio 2025-04-22 08:05:22 +02:00
parent b63606a48c
commit 1da7ee5208
21 changed files with 6480 additions and 2970 deletions

2
public/assets/js/select2.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -3,31 +3,26 @@ ini_set('display_errors', 1);
ini_set('display_startup_errors', 1); ini_set('display_startup_errors', 1);
error_reporting(E_ALL); error_reporting(E_ALL);
include('include/headscript.php'); // Assicuriamoci che carichi la connessione DB require_once __DIR__ . '/class/db-functions.php';
$dbHandler = DBHandlerSelect::getInstance();
// Connessione al database $pdo = $dbHandler->getConnection();
$conn = new mysqli($servername, $username, $password, $database);
if ($conn->connect_error) {
die(json_encode(["success" => false, "message" => "Errore di connessione: " . $conn->connect_error]));
}
// Ricezione dati dal form // Ricezione dati dal form
$user_id = isset($_POST['user_id']) ? intval($_POST['user_id']) : 0; $user_id = isset($_POST['user_id']) ? (int)$_POST['user_id'] : 0;
$first_name = isset($_POST['first_name']) ? $conn->real_escape_string($_POST['first_name']) : null; $first_name = isset($_POST['first_name']) ? htmlspecialchars($_POST['first_name']) : null;
$last_name = isset($_POST['last_name']) ? $conn->real_escape_string($_POST['last_name']) : null; $last_name = isset($_POST['last_name']) ? htmlspecialchars($_POST['last_name']) : null;
$company_name = isset($_POST['company_name']) ? $conn->real_escape_string($_POST['company_name']) : null; $company_name = isset($_POST['company_name']) ? htmlspecialchars($_POST['company_name']) : null;
$tax_code = isset($_POST['tax_code']) ? $conn->real_escape_string($_POST['tax_code']) : null; $tax_code = isset($_POST['tax_code']) ? htmlspecialchars($_POST['tax_code']) : null;
$email = isset($_POST['email']) ? $conn->real_escape_string($_POST['email']) : null; $email = isset($_POST['email']) ? htmlspecialchars($_POST['email']) : null;
$phone = isset($_POST['phone']) ? $conn->real_escape_string($_POST['phone']) : null; $phone = isset($_POST['phone']) ? htmlspecialchars($_POST['phone']) : null;
$address = isset($_POST['address']) ? $conn->real_escape_string($_POST['address']) : null; $address = isset($_POST['address']) ? htmlspecialchars($_POST['address']) : null;
$postal_code = isset($_POST['postal_code']) ? $conn->real_escape_string($_POST['postal_code']) : null; $postal_code = isset($_POST['postal_code']) ? htmlspecialchars($_POST['postal_code']) : null;
$city = isset($_POST['city']) ? $conn->real_escape_string($_POST['city']) : null; $city = isset($_POST['city']) ? htmlspecialchars($_POST['city']) : null;
$province = isset($_POST['province']) ? $conn->real_escape_string($_POST['province']) : null; $province = isset($_POST['province']) ? htmlspecialchars($_POST['province']) : null;
$country = isset($_POST['country']) ? intval($_POST['country']) : null; $country = isset($_POST['country']) ? (int)$_POST['country'] : null;
$owner_type = isset($_POST['owner_type']) ? $conn->real_escape_string($_POST['owner_type']) : null; $owner_type = isset($_POST['owner_type']) ? htmlspecialchars($_POST['owner_type']) : null;
$role = isset($_POST['role']) ? $conn->real_escape_string($_POST['role']) : null; $role = isset($_POST['role']) ? htmlspecialchars($_POST['role']) : null;
$notes = isset($_POST['notes']) ? $conn->real_escape_string($_POST['notes']) : null; $notes = isset($_POST['notes']) ? htmlspecialchars($_POST['notes']) : null;
// Validazione dei campi obbligatori // Validazione dei campi obbligatori
if (!$user_id || !$tax_code || !$email || !$owner_type) { if (!$user_id || !$tax_code || !$email || !$owner_type) {
@ -40,49 +35,44 @@ if ($owner_type === "individual") {
} }
// Controlla se il proprietario esiste già (evita duplicati) // Controlla se il proprietario esiste già (evita duplicati)
$queryCheck = $conn->prepare("SELECT owner_id FROM property_owners WHERE tax_code = ?"); $stmt = $pdo->prepare("SELECT owner_id FROM property_owners WHERE tax_code = ?");
$queryCheck->bind_param("s", $tax_code); $stmt->execute([$tax_code]);
$queryCheck->execute(); if ($stmt->fetch()) {
$resultCheck = $queryCheck->get_result();
if ($resultCheck->num_rows > 0) {
die(json_encode(["success" => false, "message" => "Esiste già un proprietario con questo Codice Fiscale/Partita IVA."])); die(json_encode(["success" => false, "message" => "Esiste già un proprietario con questo Codice Fiscale/Partita IVA."]));
} }
// Inserisci nuovo proprietario // Inserisci nuovo proprietario
$queryInsert = $conn->prepare(" $stmt = $pdo->prepare("
INSERT INTO property_owners (user_id, first_name, last_name, company_name, tax_code, email, phone, address, postal_code, city, province, country, owner_type, role, notes) INSERT INTO property_owners (user_id, first_name, last_name, company_name, tax_code, email, phone, address, postal_code, city, province, country, owner_type, role, notes)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
"); ");
try {
if ($queryInsert === false) { $stmt->execute([
die(json_encode(["success" => false, "message" => "Errore nella query: " . $conn->error])); $user_id,
$first_name,
$last_name,
$company_name,
$tax_code,
$email,
$phone,
$address,
$postal_code,
$city,
$province,
$country,
$owner_type,
$role,
$notes
]);
$owner_id = $pdo->lastInsertId();
$owner_name = $owner_type === "individual" ? "$first_name $last_name" : $company_name;
echo json_encode([
"success" => true,
"message" => "Proprietario aggiunto con successo!",
"owner_id" => $owner_id,
"owner_name" => $owner_name,
"tax_code" => $tax_code
]);
} catch (PDOException $e) {
die(json_encode(["success" => false, "message" => "Errore nell'inserimento: " . $e->getMessage()]));
} }
$queryInsert->bind_param(
"issssssssssssss",
$user_id,
$first_name,
$last_name,
$company_name,
$tax_code,
$email,
$phone,
$address,
$postal_code,
$city,
$province,
$country,
$owner_type,
$role,
$notes
);
if ($queryInsert->execute()) {
echo json_encode(["success" => true, "message" => "Proprietario aggiunto con successo!", "owner_id" => $queryInsert->insert_id, "owner_name" => $first_name . " " . $last_name, "tax_code" => $tax_code]);
} else {
die(json_encode(["success" => false, "message" => "Errore nell'inserimento: " . $queryInsert->error]));
}
// Chiude la connessione
$conn->close();

View File

@ -3,20 +3,15 @@ ini_set('display_errors', 1);
ini_set('display_startup_errors', 1); ini_set('display_startup_errors', 1);
error_reporting(E_ALL); error_reporting(E_ALL);
include('include/headscript.php'); require_once __DIR__ . '/class/db-functions.php';
$dbHandler = DBHandlerSelect::getInstance();
// Connessione al database $pdo = $dbHandler->getConnection();
$conn = new mysqli($servername, $username, $password, $database);
if ($conn->connect_error) {
die(json_encode(["success" => false, "message" => "Errore di connessione: " . $conn->connect_error]));
}
// Recupera i dati inviati tramite POST // Recupera i dati inviati tramite POST
$idhome = isset($_POST['idhome']) ? intval($_POST['idhome']) : 0; $idhome = isset($_POST['idhome']) ? (int)$_POST['idhome'] : 0;
$owner_id = isset($_POST['owner_id']) ? intval($_POST['owner_id']) : 0; $owner_id = isset($_POST['owner_id']) ? (int)$_POST['owner_id'] : 0;
$ownership_percentage = isset($_POST['ownership_percentage']) ? floatval($_POST['ownership_percentage']) : null; $ownership_percentage = isset($_POST['ownership_percentage']) ? (float)$_POST['ownership_percentage'] : null;
$notes = isset($_POST['notes']) ? $conn->real_escape_string($_POST['notes']) : null; $notes = isset($_POST['notes']) ? htmlspecialchars($_POST['notes']) : null;
// Verifica che tutti i dati siano presenti // Verifica che tutti i dati siano presenti
if ($idhome <= 0 || $owner_id <= 0 || is_null($ownership_percentage)) { if ($idhome <= 0 || $owner_id <= 0 || is_null($ownership_percentage)) {
@ -24,46 +19,30 @@ if ($idhome <= 0 || $owner_id <= 0 || is_null($ownership_percentage)) {
} }
// Controlla se il proprietario è già associato alla casa // Controlla se il proprietario è già associato alla casa
$queryCheck = $conn->prepare("SELECT 1 FROM home_owners WHERE home_id = ? AND owner_id = ?"); $stmt = $pdo->prepare("SELECT 1 FROM home_owners WHERE home_id = ? AND owner_id = ?");
$queryCheck->bind_param('ii', $idhome, $owner_id); $stmt->execute([$idhome, $owner_id]);
$queryCheck->execute(); if ($stmt->fetch()) {
$resultCheck = $queryCheck->get_result();
if ($resultCheck->num_rows > 0) {
die(json_encode(["success" => false, "message" => "Errore: Il proprietario è già associato a questa casa."])); die(json_encode(["success" => false, "message" => "Errore: Il proprietario è già associato a questa casa."]));
} }
// Calcola la somma attuale delle percentuali di proprietà // Calcola la somma attuale delle percentuali di proprietà
$queryTotal = $conn->prepare("SELECT SUM(ownership_percentage) FROM home_owners WHERE home_id = ?"); $stmt = $pdo->prepare("SELECT SUM(ownership_percentage) FROM home_owners WHERE home_id = ?");
$queryTotal->bind_param('i', $idhome); $stmt->execute([$idhome]);
$queryTotal->execute(); $currentTotal = $stmt->fetchColumn() ?: 0;
$queryTotal->bind_result($currentTotal);
$queryTotal->fetch();
$queryTotal->close();
$totalAfterInsert = $currentTotal + $ownership_percentage; $totalAfterInsert = $currentTotal + $ownership_percentage;
if ($totalAfterInsert > 100) { if ($totalAfterInsert > 100) {
die(json_encode(["success" => false, "message" => "Errore: La somma totale dei proprietari supererebbe il 100%."])); die(json_encode(["success" => false, "message" => "Errore: La somma totale dei proprietari supererebbe il 100%. Totale attuale: $currentTotal%, percentuale richiesta: $ownership_percentage%."]));
} }
// Inserisce il nuovo proprietario nella tabella home_owners // Inserisce il nuovo proprietario nella tabella home_owners
$queryInsert = $conn->prepare(" $stmt = $pdo->prepare("
INSERT INTO home_owners (home_id, owner_id, ownership_percentage, notes, created_at, updated_at) INSERT INTO home_owners (home_id, owner_id, ownership_percentage, notes, created_at, updated_at)
VALUES (?, ?, ?, ?, NOW(), NOW()) VALUES (?, ?, ?, ?, NOW(), NOW())
"); ");
try {
if ($queryInsert === false) { $stmt->execute([$idhome, $owner_id, $ownership_percentage, $notes]);
die(json_encode(["success" => false, "message" => "Errore nella preparazione della query: " . $conn->error]));
}
$queryInsert->bind_param('iids', $idhome, $owner_id, $ownership_percentage, $notes);
if ($queryInsert->execute()) {
echo json_encode(["success" => true, "message" => "Proprietario aggiunto con successo."]); echo json_encode(["success" => true, "message" => "Proprietario aggiunto con successo."]);
} else { } catch (PDOException $e) {
die(json_encode(["success" => false, "message" => "Errore nell'inserimento: " . $queryInsert->error])); die(json_encode(["success" => false, "message" => "Errore nell'inserimento: " . $e->getMessage()]));
} }
$queryInsert->close();
$conn->close();

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,48 @@
<?php
require_once dirname(__DIR__, 3) . '/vendor/autoload.php';
use Dotenv\Dotenv;
class DBHandlerSelect
{
private static $instance = null;
private $pdo;
private function __construct()
{
$dotenv = Dotenv::createImmutable(dirname(__DIR__, 3));
$dotenv->load();
$host = $_ENV['DB_HOST'];
$db = $_ENV['DB_DATABASE'];
$user = $_ENV['DB_USERNAME'];
$pass = $_ENV['DB_PASSWORD'];
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$this->pdo = new PDO($dsn, $user, $pass, $options);
} catch (PDOException $e) {
die("Database connection failed: " . $e->getMessage());
}
}
public static function getInstance()
{
if (self::$instance === null) {
self::$instance = new DBHandlerSelect();
}
return self::$instance;
}
public function getConnection()
{
return $this->pdo;
}
}

View File

@ -0,0 +1,61 @@
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use Dotenv\Dotenv;
// Carica le variabili di ambiente
require_once dirname(__DIR__, 2) . '/vendor/autoload.php'; // Assicurati che PHPMailer e Dotenv siano installati con Composer
$dotenv = Dotenv::createImmutable(dirname(__DIR__, 2)); // Se la cartella `class` è a 2 livelli sopra la root
$dotenv->load();
function sendEmail($to, $subject, $body, $attachments = [], $cc = [], $bcc = [])
{
// Configurazione SMTP
$mail = new PHPMailer(true);
try {
// Configurazione server SMTP con dati da .env
$mail->isSMTP();
$mail->Host = $_ENV['MAIL_HOST'] ?? 'smtp.example.com';
$mail->SMTPAuth = true;
$mail->Username = $_ENV['MAIL_USERNAME'] ?? 'email@example.com';
$mail->Password = $_ENV['MAIL_PASSWORD'] ?? 'password';
$mail->SMTPSecure = $_ENV['MAIL_ENCRYPTION'] ?? PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = $_ENV['MAIL_PORT'] ?? 587;
// Mittente
$mail->setFrom($_ENV['MAIL_FROM_ADDRESS'] ?? 'default@example.com', $_ENV['MAIL_FROM_NAME'] ?? 'Default Name');
// Destinatari principali
foreach ((array)$to as $recipient) {
$mail->addAddress($recipient);
}
// Destinatari CC
foreach ((array)$cc as $recipient) {
$mail->addCC($recipient);
}
// Destinatari BCC
foreach ((array)$bcc as $recipient) {
$mail->addBCC($recipient);
}
// Allegati
foreach ((array)$attachments as $file) {
$mail->addAttachment($file);
}
// Contenuto dell'email
$mail->isHTML(true);
$mail->Subject = $subject;
$mail->Body = $body;
// Invia l'email
$mail->send();
return ['success' => true, 'message' => 'Email inviata con successo.'];
} catch (Exception $e) {
return ['success' => false, 'message' => "Errore nell'invio dell'email: {$mail->ErrorInfo}"];
}
}

View File

@ -1,40 +1,96 @@
<?php <?php
include('include/headscript.php'); header('Content-Type: text/html; charset=UTF-8');
// Connessione al database // Includi il file per la connessione al database
$conn = new mysqli($servername, $username, $password, $database); require_once 'class/db-functions.php';
if ($conn->connect_error) { // Inizializza la connessione al database
die("Errore di connessione: " . $conn->connect_error); try {
$dbHandler = DBHandlerSelect::getInstance();
$pdo = $dbHandler->getConnection();
} catch (Exception $e) {
echo '<select id="ownerSelect" name="owner_id" class="form-control"><option value="">-- Seleziona --</option><option value="new_owner"> Aggiungi nuovo proprietario</option></select>';
error_log("Errore connessione database in get-available-owners.php: " . $e->getMessage());
exit();
} }
// Recupera l'ID dell'immobile e l'ID dell'utente
$iduserlogin = isset($_GET['iduser']) ? intval($_GET['iduser']) : 0;
$idhome = isset($_GET['idhome']) ? intval($_GET['idhome']) : 0; $idhome = isset($_GET['idhome']) ? intval($_GET['idhome']) : 0;
// Recupera tutti i proprietari disponibili per l'assegnazione // Debug: logga i valori di $iduserlogin e $idhome
$queryAvailableOwners = $conn->prepare(" error_log("Valori iniziali - idhome: $idhome, iduserlogin: $iduserlogin");
SELECT owner_id, first_name, last_name, company_name, tax_code
FROM property_owners
WHERE user_id = ?
AND owner_id NOT IN (
SELECT owner_id FROM home_owners WHERE home_id = ?
)
");
$queryAvailableOwners->bind_param('ii', $iduserlogin, $idhome);
$queryAvailableOwners->execute();
$resultAvailableOwners = $queryAvailableOwners->get_result();
// Genera il nuovo dropdown // Controlla che i parametri siano validi
echo '<select class="form-control" id="ownerSelect" name="owner_id" required>'; if ($idhome <= 0 || $iduserlogin <= 0) {
echo '<option value="">-- Seleziona --</option>'; echo '<select id="ownerSelect" name="owner_id" class="form-control"><option value="">-- Seleziona --</option><option value="new_owner"> Aggiungi nuovo proprietario</option></select>';
while ($availableOwner = $resultAvailableOwners->fetch_assoc()) { error_log("Parametri non validi in get-available-owners.php: idhome=$idhome, iduserlogin=$iduserlogin");
echo '<option value="' . $availableOwner['owner_id'] . '">'; exit();
echo htmlspecialchars($availableOwner['first_name'] . ' ' . $availableOwner['last_name']);
if ($availableOwner['company_name']) {
echo ' (' . htmlspecialchars($availableOwner['company_name']) . ')';
}
echo ' - ' . htmlspecialchars($availableOwner['tax_code']);
echo '</option>';
} }
echo '</select>';
$conn->close(); // Debug: verifica il numero di proprietari associati all'immobile
try {
$stmt = $pdo->prepare("SELECT owner_id FROM home_owners WHERE home_id = ?");
$stmt->execute([$idhome]);
$associatedOwners = $stmt->fetchAll(PDO::FETCH_COLUMN, 0);
error_log("Proprietari associati all'immobile (idhome=$idhome): " . json_encode($associatedOwners));
} catch (Exception $e) {
error_log("Errore query associati in get-available-owners.php: " . $e->getMessage());
$associatedOwners = [];
}
// Debug: verifica tutti i proprietari dell'utente
try {
$stmt = $pdo->prepare("SELECT owner_id, first_name, last_name FROM property_owners WHERE user_id = ?");
$stmt->execute([$iduserlogin]);
$allOwners = $stmt->fetchAll(PDO::FETCH_ASSOC);
error_log("Tutti i proprietari dell'utente (iduser=$iduserlogin): " . json_encode($allOwners));
} catch (Exception $e) {
error_log("Errore query tutti i proprietari in get-available-owners.php: " . $e->getMessage());
$allOwners = [];
}
// Recupera i proprietari disponibili
try {
$stmt = $pdo->prepare("
SELECT
po.owner_id,
po.first_name,
po.last_name,
po.company_name,
po.tax_code
FROM
property_owners po
LEFT JOIN
home_owners ho ON po.owner_id = ho.owner_id AND ho.home_id = ?
WHERE
po.user_id = ?
AND ho.owner_id IS NULL
");
$stmt->execute([$idhome, $iduserlogin]);
$availableOwners = $stmt->fetchAll(PDO::FETCH_ASSOC);
error_log("Proprietari disponibili per idhome=$idhome e iduser=$iduserlogin: " . json_encode($availableOwners));
} catch (Exception $e) {
echo '<select id="ownerSelect" name="owner_id" class="form-control"><option value="">-- Seleziona --</option><option value="new_owner"> Aggiungi nuovo proprietario</option></select>';
error_log("Errore query in get-available-owners.php: " . $e->getMessage());
exit();
}
?>
<select id="ownerSelect" name="owner_id" class="form-control">
<option value="">-- Seleziona --</option>
<?php if (!empty($availableOwners)) { ?>
<?php foreach ($availableOwners as $availableOwner) { ?>
<option value="<?php echo $availableOwner['owner_id']; ?>">
<?php
echo htmlspecialchars($availableOwner['first_name'] . ' ' . $availableOwner['last_name']);
if ($availableOwner['company_name']) {
echo ' (' . htmlspecialchars($availableOwner['company_name']) . ')';
}
echo ' - ' . htmlspecialchars($availableOwner['tax_code']);
?>
</option>
<?php } ?>
<?php } ?>
<option value="new_owner"> Aggiungi nuovo proprietario</option>
</select>

View File

@ -1,14 +1,22 @@
<?php <?php
include('include/headscript.php'); header('Content-Type: text/html; charset=UTF-8');
$conn = new mysqli($servername, $username, $password, $database);
if ($conn->connect_error) { require_once 'class/db-functions.php';
die("Errore di connessione: " . $conn->connect_error);
}
// Inizializza la connessione al database
$dbHandler = DBHandlerSelect::getInstance();
$pdo = $dbHandler->getConnection();
// Recupera l'ID dell'immobile
$idhome = isset($_GET['idhome']) ? intval($_GET['idhome']) : 0; $idhome = isset($_GET['idhome']) ? intval($_GET['idhome']) : 0;
$queryOwners = $conn->prepare(" if ($idhome <= 0) {
echo '<p class="text-muted">Errore: ID immobile non valido.</p>';
exit();
}
// Recupera i proprietari associati all'immobile
$stmt = $pdo->prepare("
SELECT SELECT
po.owner_id, po.owner_id,
po.first_name, po.first_name,
@ -25,13 +33,12 @@ $queryOwners = $conn->prepare("
WHERE WHERE
ho.home_id = ? ho.home_id = ?
"); ");
$queryOwners->bind_param('i', $idhome); $stmt->execute([$idhome]);
$queryOwners->execute(); $owners = $stmt->fetchAll(PDO::FETCH_ASSOC);
$resultOwners = $queryOwners->get_result();
$totalPercentage = 0; if (!empty($owners)) {
?>
echo '<table class="table table-bordered"> <table class="table table-bordered">
<thead> <thead>
<tr> <tr>
<th>Nome</th> <th>Nome</th>
@ -41,32 +48,35 @@ echo '<table class="table table-bordered">
<th>Azioni</th> <th>Azioni</th>
</tr> </tr>
</thead> </thead>
<tbody>'; <tbody id="ownersTableBody">
<?php
while ($owner = $resultOwners->fetch_assoc()) { $totalPercentage = 0;
$totalPercentage += $owner['ownership_percentage']; foreach ($owners as $owner) {
echo "<tr> $totalPercentage += $owner['ownership_percentage'];
<td>" . htmlspecialchars($owner['first_name'] . ' ' . $owner['last_name']) . "</td> echo "<tr>
<td>" . htmlspecialchars($owner['tax_code']) . "</td> <td>" . htmlspecialchars($owner['first_name'] . ' ' . $owner['last_name']) . "</td>
<td class='ownership-percentage'>" . htmlspecialchars($owner['ownership_percentage']) . "</td> <td>" . htmlspecialchars($owner['tax_code']) . "</td>
<td>" . htmlspecialchars($owner['notes']) . "</td> <td class='ownership-percentage'>" . htmlspecialchars($owner['ownership_percentage']) . "</td>
<td> <td>" . htmlspecialchars($owner['notes']) . "</td>
<button class='btn btn-danger btn-sm remove-owner-btn' data-id='" . $owner['owner_id'] . "'> <td>
<i class='fas fa-trash-alt'></i> Rimuovi <button class='btn btn-danger btn-sm remove-owner-btn' data-id='" . $owner['owner_id'] . "'>
</button> <i class='fas fa-trash-alt'></i> Rimuovi
</td> </button>
</tr>"; </td>
</tr>";
}
?>
</tbody>
<tfoot>
<tr>
<td colspan="2"><strong>Totale % Proprietà:</strong></td>
<td id="totalOwnership" class="font-weight-bold text-center"><?php echo $totalPercentage; ?>%</td>
<td colspan="2"></td>
</tr>
</tfoot>
</table>
<?php
} else {
echo '<p class="text-muted">Nessun proprietario associato.</p>';
} }
?>
echo '</tbody>
<tfoot>
<tr>
<td colspan="2"><strong>Totale % Proprietà:</strong></td>
<td id="totalOwnership" class="font-weight-bold text-center">' . $totalPercentage . '%</td>
<td colspan="2"></td>
</tr>
</tfoot>
</table>';
$queryOwners->close();
$conn->close();

View File

@ -264,6 +264,39 @@ $result = $stmt->get_result();
.box-home:hover .action-menu { .box-home:hover .action-menu {
opacity: 1; opacity: 1;
} }
/* Stile per il nuovo banner */
.header-banner {
position: relative;
background-size: cover;
background-position: center;
border-radius: 10px;
height: 150px;
/* Altezza del banner */
overflow: hidden;
}
.header-banner-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(to right, rgba(30, 58, 138, 0.8), rgba(255, 255, 255, 0.2));
/* Gradiente sovrapposto */
padding: 20px;
display: flex;
align-items: center;
}
.header-banner-title {
color: #ffffff;
font-size: 28px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.03em;
margin: 0;
}
</style> </style>
</head> </head>
@ -290,10 +323,22 @@ $result = $stmt->get_result();
</div> </div>
</div> </div>
<!-- Nuovo Banner -->
<div class="row mb-4">
<div class="col-12">
<div class="header-banner" style="background-image: url('path/to/your/image.jpg');">
<div class="header-banner-overlay">
<h3 class="header-banner-title">Immobili</h3>
</div>
</div>
</div>
</div>
<div class="row mb-3"> <div class="row mb-3">
<div class="col-12 d-flex justify-content-start align-items-center gap-3"> <div class="col-12 d-flex justify-content-start align-items-center gap-3">
<a href="manage-home.php" class="btn btn-success"> <a href="manage-home.php" class="btn btn-success">
<i class="fas fa-plus"></i> Aggiungi Casa/Terreno <i class="fas fa-plus"></i> Aggiungi Nuovo
</a> </a>
<button id="toggleViewBtn" class="btn btn-info ms-2"> <button id="toggleViewBtn" class="btn btn-info ms-2">
@ -301,8 +346,6 @@ $result = $stmt->get_result();
</button> </button>
</div> </div>
</div> </div>
<!-- table view --> <!-- table view -->
<div id="tableView" style="display: none;"> <div id="tableView" style="display: none;">
@ -317,21 +360,16 @@ $result = $stmt->get_result();
<tr> <tr>
<th>Foto</th> <th>Foto</th>
<th>Nome di Riferimento</th> <th>Nome di Riferimento</th>
<th>Città / Nazione</th>
<th>Indirizzo</th>
<th>Proprietari</th> <th>Proprietari</th>
<th>Città / Nazione</th>
<th>Action</th> <th>Action</th>
</tr> </tr>
<tr> <tr>
<!-- Campi di input per i filtri --> <!-- Campi di input per i filtri -->
<th></th> <th></th>
<th><input type="text" placeholder="Cerca Nome" class="form-control form-control-sm"></th> <th><input type="text" placeholder="Cerca Nome" class="form-control form-control-sm"></th>
<th><input type="text" placeholder="Cerca Città" class="form-control form-control-sm"></th>
<th><input type="text" placeholder="Cerca Indirizzo" class="form-control form-control-sm"></th>
<th><input type="text" placeholder="Cerca Proprietari" class="form-control form-control-sm"></th> <th><input type="text" placeholder="Cerca Proprietari" class="form-control form-control-sm"></th>
<th><input type="text" placeholder="Cerca Città" class="form-control form-control-sm"></th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
@ -340,25 +378,17 @@ $result = $stmt->get_result();
<tr> <tr>
<!-- Thumbnail immagine --> <!-- Thumbnail immagine -->
<td> <td>
<img src="mainphoto/<?php echo htmlspecialchars($row['mainphoto'] ?? 'default.jpg'); ?>" <a href="manage-home.php?idhome=<?php echo $row['idhome']; ?>">
class="img-thumbnail open-photo" <img src="mainphoto/<?php echo htmlspecialchars($row['mainphoto'] ?? 'default.jpg'); ?>"
style="width: 80px; height: 80px; object-fit: cover; cursor: pointer;" class="img-thumbnail open-photo"
alt="<?php echo htmlspecialchars($row['name']); ?>" style="width: 80px; height: 80px; object-fit: cover; cursor: pointer;"
data-toggle="modal" data-target="#photoModal" alt="<?php echo htmlspecialchars($row['name']); ?>">
data-src="mainphoto/<?php echo htmlspecialchars($row['mainphoto'] ?? 'default.jpg'); ?>"> </a>
</td> </td>
<!-- Nome immobile --> <!-- Nome immobile -->
<td><?php echo htmlspecialchars($row['name']); ?></td> <td><?php echo htmlspecialchars($row['name']); ?></td>
<!-- Città e Nazione -->
<td><?php echo htmlspecialchars($row['city']); ?>, <?php echo htmlspecialchars($row['country']); ?></td>
<!-- Indirizzo -->
<td><?php echo htmlspecialchars($row['address']); ?></td>
<!-- Proprietari + Bottone --> <!-- Proprietari + Bottone -->
<td> <td>
<?php echo nl2br(htmlspecialchars($row['owner_names'])); ?> <?php echo nl2br(htmlspecialchars($row['owner_names'])); ?>
@ -381,7 +411,10 @@ $result = $stmt->get_result();
</a> </a>
</td> </td>
<!-- azioni --> <!-- Città e Nazione -->
<td><?php echo htmlspecialchars($row['city']); ?>, <?php echo htmlspecialchars($row['country']); ?></td>
<!-- Azioni -->
<td class="text-nowrap"> <td class="text-nowrap">
<div class="dropdown"> <div class="dropdown">
<button class="btn btn-light btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false"> <button class="btn btn-light btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
@ -406,12 +439,7 @@ $result = $stmt->get_result();
</ul> </ul>
</div> </div>
</td> </td>
</tr> </tr>
<?php } ?> <?php } ?>
</tbody> </tbody>
</table> </table>
@ -432,9 +460,12 @@ $result = $stmt->get_result();
while ($row = $result->fetch_assoc()) { ?> while ($row = $result->fetch_assoc()) { ?>
<div class="col-md-3 col-sm-6 mb-4"> <!-- 4 per riga su desktop, 2 su tablet --> <div class="col-md-3 col-sm-6 mb-4"> <!-- 4 per riga su desktop, 2 su tablet -->
<div class="card shadow-sm border-0 position-relative box-home"> <div class="card shadow-sm border-0 position-relative box-home">
<img src="mainphoto/<?php echo htmlspecialchars($row['mainphoto'] ?? 'default.jpg'); ?>" <a href="manage-home.php?idhome=<?php echo $row['idhome']; ?>">
class="card-img-top" <img src="mainphoto/<?php echo htmlspecialchars($row['mainphoto'] ?? 'default.jpg'); ?>"
alt="<?php echo htmlspecialchars($row['name']); ?>"> class="card-img-top"
alt="<?php echo htmlspecialchars($row['name']); ?>">
</a>
<!-- Pulsante 3 puntini --> <!-- Pulsante 3 puntini -->
<!-- Contenitore per i bottoni (Proprietari + Menu Azioni) --> <!-- Contenitore per i bottoni (Proprietari + Menu Azioni) -->

View File

@ -0,0 +1,95 @@
<!-- ========== Left Sidebar Start ========== -->
<div class="left side-menu">
<button type="button" class="button-menu-mobile button-menu-mobile-topbar open-left waves-effect">
<i class="ion-close"></i>
</button>
<!-- LOGO -->
<div class="topbar-left">
<div class="text-center bg-logo">
<a href="index.html" class="logo">
<img src="../assets/img/logotraspcasetta.png" alt="CasaDoc Logo" style="height: 40px; vertical-align: middle;">
CasaDoc
</a>
<!-- <a href="index.html" class="logo"><img src="assets/images/logo.png" height="24" alt="logo"></a> -->
</div>
</div>
<div class="sidebar-user">
<img src="assets/images/users/man.png" alt="user" class="rounded-circle img-thumbnail mb-1">
<h6 class=""><?php echo $_SESSION["nameuser"]; ?> <?php echo $_SESSION["surnameuser"]; ?> </h6>
<p class=" online-icon text-dark"><i class="mdi mdi-record text-success"></i>online</p>
<ul class="list-unstyled list-inline mb-0 mt-2">
<li class="list-inline-item">
<a href="../" class="" data-toggle="tooltip" data-placement="top" title="Profile"><i class="dripicons-user text-purple"></i></a>
</li>
<li class="list-inline-item">
<a href="../" class="" data-toggle="tooltip" data-placement="top" title="Settings"><i class="dripicons-gear text-dark"></i></a>
</li>
<li class="list-inline-item">
<a href="../logout" class="" data-toggle="tooltip" data-placement="top" title="Log out"><i class="dripicons-power text-danger"></i></a>
</li>
</ul>
</div>
<div class="sidebar-inner slimscrollleft">
<div id="sidebar-menu">
<ul>
<!-- Sezione Main -->
<li class="menu-title">Main</li>
<li>
<a href="index.php" class="waves-effect">
<i class="fas fa-tachometer-alt text-danger"></i>
<span> Dashboard </span>
</a>
</li>
<!-- Sezione Immobili -->
<li class="menu-title">Sezioni</li>
<li>
<a href="homes-list.php" class="waves-effect">
<i class="fas fa-home text-primary"></i>
<span> I miei immobili </span>
</a>
</li>
<li>
<a href="person-list.php" class="waves-effect">
<i class="fas fa-users text-success"></i>
<span> Persone/Società </span>
</a>
</li>
<li>
<a href="shared-homes.php" class="waves-effect">
<i class="fas fa-share-alt text-info"></i>
<span> Immobili Condivisi </span>
</a>
</li>
<!-- Sezione Amministrazione -->
<li class="menu-title">Amministrazione</li>
<li>
<a href="admin.php" class="waves-effect">
<i class="fas fa-cogs text-danger"></i>
<span> Admin Page </span>
</a>
</li>
<li class="has_sub">
<a href="pages-blank.html" target="_blank" class="waves-effect">
<i class="fas fa-folder"></i>
<span> Template </span>
<span class="float-right">
<i class="mdi mdi-chevron-right"></i>
</span>
</a>
<ul class="list-unstyled">
<li><a href="pages-blank.html"><i class="fas fa-file"></i> Blank Page</a></li>
</ul>
</li>
</ul>
</div>
<div class="clearfix"></div>
</div> <!-- end sidebarinner -->
</div>
<!-- Left Sidebar End -->

View File

@ -4,90 +4,63 @@
<i class="ion-close"></i> <i class="ion-close"></i>
</button> </button>
<!-- LOGO -->
<div class="topbar-left">
<div class="text-center bg-logo">
<a href="index.html" class="logo">
<img src="../assets/img/logotraspcasetta.png" alt="CasaDoc Logo" style="height: 40px; vertical-align: middle;">
CasaDoc
</a>
<!-- <a href="index.html" class="logo"><img src="assets/images/logo.png" height="24" alt="logo"></a> -->
</div>
</div>
<div class="sidebar-user">
<img src="assets/images/users/man.png" alt="user" class="rounded-circle img-thumbnail mb-1">
<h6 class=""><?php echo $_SESSION["nameuser"]; ?> <?php echo $_SESSION["surnameuser"]; ?> </h6>
<p class=" online-icon text-dark"><i class="mdi mdi-record text-success"></i>online</p>
<ul class="list-unstyled list-inline mb-0 mt-2">
<li class="list-inline-item">
<a href="../" class="" data-toggle="tooltip" data-placement="top" title="Profile"><i class="dripicons-user text-purple"></i></a>
</li>
<li class="list-inline-item">
<a href="../" class="" data-toggle="tooltip" data-placement="top" title="Settings"><i class="dripicons-gear text-dark"></i></a>
</li>
<li class="list-inline-item">
<a href="../logout" class="" data-toggle="tooltip" data-placement="top" title="Log out"><i class="dripicons-power text-danger"></i></a>
</li>
</ul>
</div>
<div class="sidebar-inner slimscrollleft"> <div class="sidebar-inner slimscrollleft">
<div id="sidebar-menu"> <div id="sidebar-menu">
<ul> <ul>
<!-- Sezione Main --> <!-- Sezione Main -->
<li class="menu-title">Main</li>
<li> <li>
<a href="index.php" class="waves-effect"> <a href="index.php" class="sidebar-btn waves-effect">
<i class="fas fa-tachometer-alt text-danger"></i> <div class="sidebar-btn-icon">
<span> Dashboard </span> <i class="fas fa-tachometer-alt"></i>
</div>
<span>Dashboard</span>
</a> </a>
</li> </li>
<!-- Sezione Immobili --> <!-- Sezione Immobili -->
<li class="menu-title">Sezioni</li>
<li> <li>
<a href="homes-list.php" class="waves-effect"> <a href="homes-list.php" class="sidebar-btn waves-effect active">
<i class="fas fa-home text-primary"></i> <div class="sidebar-btn-icon">
<span> I miei immobili </span> <i class="fas fa-home"></i>
</div>
<span>I miei immobili</span>
</a> </a>
</li> </li>
<li> <li>
<a href="person-list.php" class="waves-effect"> <a href="person-list.php" class="sidebar-btn waves-effect">
<i class="fas fa-users text-success"></i> <div class="sidebar-btn-icon">
<span> Persone/Società </span> <i class="fas fa-users"></i>
</div>
<span>Persone/Società</span>
</a> </a>
</li> </li>
<li> <li>
<a href="shared-homes.php" class="waves-effect"> <a href="shared-homes.php" class="sidebar-btn waves-effect">
<i class="fas fa-share-alt text-info"></i> <div class="sidebar-btn-icon">
<span> Immobili Condivisi </span> <i class="fas fa-share-alt"></i>
</div>
<span>Immobili Condivisi</span>
</a> </a>
</li> </li>
<!-- Sezione Amministrazione --> <!-- Sezione Amministrazione -->
<li class="menu-title">Amministrazione</li>
<li> <li>
<a href="admin.php" class="waves-effect"> <a href="admin.php" class="sidebar-btn waves-effect">
<i class="fas fa-cogs text-danger"></i> <div class="sidebar-btn-icon">
<span> Admin Page </span> <i class="fas fa-cogs"></i>
</div>
<span>Admin Page</span>
</a> </a>
</li> </li>
<li class="has_sub"> <li>
<a href="pages-blank.html" target="_blank" class="waves-effect"> <a href="pages-blank.html" target="_blank" class="sidebar-btn waves-effect">
<i class="fas fa-folder"></i> <div class="sidebar-btn-icon">
<span> Template </span> <i class="fas fa-folder"></i>
<span class="float-right"> </div>
<i class="mdi mdi-chevron-right"></i> <span>Template</span>
</span>
</a> </a>
<ul class="list-unstyled">
<li><a href="pages-blank.html"><i class="fas fa-file"></i> Blank Page</a></li>
</ul>
</li> </li>
</ul> </ul>
</div> </div>
<div class="clearfix"></div> <div class="clearfix"></div>
</div> <!-- end sidebarinner --> </div> <!-- end sidebarinner -->

View File

@ -1,76 +1,43 @@
<?php
/*
// Crea la connessione
$conn = new mysqli($servername, $username, $password, $database);
// Controlla la connessione
if ($conn->connect_error) {
die("Connessione fallita: " . $conn->connect_error);
}
// Query SQL per estrarre le lingue
$sql = "SELECT languagename, languageflag, languageacronym FROM languagesdrop";
$result = $conn->query($sql);
$languages = [];
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$languages[] = $row;
}
}
// Chiudi la connessione
$conn->close();
*/ ?>
<!-- Top Bar Start --> <!-- Top Bar Start -->
<div class="topbar"> <div class="topbar">
<nav class="navbar-custom"> <nav class="navbar-custom">
<ul class="list-inline menu-left mb-0">
<ul class="list-inline float-right mb-0"> <!-- Aggiungi il logo qui -->
<!-- language--> <li class="float-left">
<!-- <li class="list-inline-item dropdown notification-list hide-phone"> <div class="logo-container">
<a class="nav-link dropdown-toggle arrow-none waves-effect text-white" data-toggle="dropdown" href="#" role="button" <a href="index.html" class="logo">
aria-haspopup="false" aria-expanded="false"> <img src="../assets/img/logotraspcasetta.png" alt="CasaDoc Logo" style="height: 40px; vertical-align: middle;">
English <img src="assets/images/flags/us_flag.jpg" class="ml-2" height="16" alt="" /> CasaDoc
</a> </a>
<div class="dropdown-menu dropdown-menu-right language-switch">
</div> </div>
</li> --> </li>
</ul>
<li class="float-left">
<button class="button-menu-mobile open-left waves-light waves-effect">
<i class="mdi mdi-menu"></i>
</button>
</li>
<ul class="list-inline float-right mb-0">
<li class="list-inline-item dropdown notification-list"> <li class="list-inline-item dropdown notification-list">
<a class="nav-link dropdown-toggle arrow-none waves-effect nav-user" data-toggle="dropdown" href="#" role="button" <a class="nav-link dropdown-toggle arrow-none waves-effect nav-user" data-toggle="dropdown" href="#" role="button"
aria-haspopup="false" aria-expanded="false"> aria-haspopup="false" aria-expanded="false">
<img src="assets/images/users/man.png" alt="user" class="rounded-circle"> <img src="assets/images/users/man.png" alt="user" class="rounded-circle">
<span class="ml-2"><?php echo $nameuser . ' ' . $surnameuser; ?></span>
</a> </a>
<div class="dropdown-menu dropdown-menu-right profile-dropdown "> <div class="dropdown-menu dropdown-menu-right profile-dropdown">
<!-- item--> <!-- item-->
<div class="dropdown-item noti-title"> <div class="dropdown-item noti-title">
<h5>Welcome</h5> <h5>Welcome</h5>
</div> </div>
<a class="dropdown-item" href="../"><i class="mdi mdi-account-circle m-r-5 text-muted"></i> Profilo Utente</a> <a class="dropdown-item" href="../"><i class="mdi mdi-account-circle m-r-5 text-muted"></i> Profilo Utente</a>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a class="dropdown-item" href="#"><i class="mdi mdi-logout m-r-5 text-muted"></i> Logout</a> <a class="dropdown-item" href="#"><i class="mdi mdi-logout m-r-5 text-muted"></i> Logout</a>
</div> </div>
</li> </li>
</ul> </ul>
<ul class="list-inline menu-left mb-0">
<li class="float-left">
<button class="button-menu-mobile open-left waves-light waves-effect">
<i class="mdi mdi-menu"></i>
</button>
</li>
</ul>
<div class="clearfix"></div> <div class="clearfix"></div>
</nav> </nav>
</div> </div>

View File

@ -1,16 +1,9 @@
<?php include('include/headscript.php'); ?> <?php include('include/headscript.php'); ?>
<?php <?php
// Connessione al database e avvio sessione // Connessione al database
$conn = new mysqli($servername, $username, $password, $database); $conn = new mysqli($servername, $username, $password, $database);
// Verifica connessione
if ($conn->connect_error) {
die("Errore di connessione: " . $conn->connect_error);
}
// Recupera l'id utente loggato
$iduserlogin = $_SESSION['iduserlogin']; $iduserlogin = $_SESSION['iduserlogin'];
// Calcolo del numero di immobili // Calcolo del numero di immobili
$queryHomes = $conn->prepare("SELECT COUNT(*) AS total_homes FROM home WHERE iduser = ?"); $queryHomes = $conn->prepare("SELECT COUNT(*) AS total_homes FROM home WHERE iduser = ?");
$queryHomes->bind_param('i', $iduserlogin); $queryHomes->bind_param('i', $iduserlogin);
@ -37,13 +30,8 @@ $queryDocuments->bind_param('i', $iduserlogin);
$queryDocuments->execute(); $queryDocuments->execute();
$resultDocuments = $queryDocuments->get_result(); $resultDocuments = $queryDocuments->get_result();
$totalDocuments = $resultDocuments->fetch_assoc()['total_documents']; $totalDocuments = $resultDocuments->fetch_assoc()['total_documents'];
?>
<?php
// Connessione al database
$conn = new mysqli($servername, $username, $password, $database);
// Recupera l'id utente loggato // Recupera l'id utente loggato
$iduserlogin = $_SESSION['iduserlogin'];
// Query per ottenere le case dell'utente // Query per ottenere le case dell'utente
$sql = " $sql = "
@ -90,7 +78,7 @@ $result = $stmt->get_result();
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Elenco delle tue case</title> <title>Elenco dei tuoi immobili</title>
<!-- Bootstrap 4 CSS --> <!-- Bootstrap 4 CSS -->
<link href="assets/css/bootstrap.min.css" rel="stylesheet" type="text/css"> <link href="assets/css/bootstrap.min.css" rel="stylesheet" type="text/css">
@ -303,6 +291,39 @@ $result = $stmt->get_result();
.box-home:hover .action-menu { .box-home:hover .action-menu {
opacity: 1; opacity: 1;
} }
/* Stile per il nuovo banner */
.header-banner {
position: relative;
background-size: cover;
background-position: center;
border-radius: 10px;
height: 150px;
/* Altezza del banner */
overflow: hidden;
}
.header-banner-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(to right, rgba(30, 58, 138, 0.8), rgba(255, 255, 255, 0.2));
/* Gradiente sovrapposto */
padding: 20px;
display: flex;
align-items: center;
}
.header-banner-title {
color: #ffffff;
font-size: 28px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.03em;
margin: 0;
}
</style> </style>
</head> </head>
@ -324,7 +345,7 @@ $result = $stmt->get_result();
<li class="breadcrumb-item active">Elenco Case</li> <li class="breadcrumb-item active">Elenco Case</li>
</ol> </ol>
</div> </div>
<h4 class="page-title">Elenco dei tuoi immobili</h4> <h4 class="page-title">Elenco delle tue case</h4>
</div> </div>
</div> </div>
</div> </div>
@ -394,10 +415,21 @@ $result = $stmt->get_result();
</div> </div>
</div> </div>
<!-- Nuovo Banner -->
<div class="row mb-4">
<div class="col-12">
<div class="header-banner" style="background-image: url('path/to/your/image.jpg');">
<div class="header-banner-overlay">
<h3 class="header-banner-title">Immobili</h3>
</div>
</div>
</div>
</div>
<div class="row mb-3"> <div class="row mb-3">
<div class="col-12 d-flex justify-content-start align-items-center gap-3"> <div class="col-12 d-flex justify-content-start align-items-center gap-3">
<a href="manage-home.php" class="btn btn-success"> <a href="manage-home.php" class="btn btn-success">
<i class="fas fa-plus"></i> Aggiungi Casa/Terreno <i class="fas fa-plus"></i> Aggiungi Nuovo
</a> </a>
<button id="toggleViewBtn" class="btn btn-info ms-2"> <button id="toggleViewBtn" class="btn btn-info ms-2">
@ -405,8 +437,6 @@ $result = $stmt->get_result();
</button> </button>
</div> </div>
</div> </div>
<!-- table view --> <!-- table view -->
<div id="tableView" style="display: none;"> <div id="tableView" style="display: none;">
@ -421,21 +451,16 @@ $result = $stmt->get_result();
<tr> <tr>
<th>Foto</th> <th>Foto</th>
<th>Nome di Riferimento</th> <th>Nome di Riferimento</th>
<th>Città / Nazione</th>
<th>Indirizzo</th>
<th>Proprietari</th> <th>Proprietari</th>
<th>Città / Nazione</th>
<th>Action</th> <th>Action</th>
</tr> </tr>
<tr> <tr>
<!-- Campi di input per i filtri --> <!-- Campi di input per i filtri -->
<th></th> <th></th>
<th><input type="text" placeholder="Cerca Nome" class="form-control form-control-sm"></th> <th><input type="text" placeholder="Cerca Nome" class="form-control form-control-sm"></th>
<th><input type="text" placeholder="Cerca Città" class="form-control form-control-sm"></th>
<th><input type="text" placeholder="Cerca Indirizzo" class="form-control form-control-sm"></th>
<th><input type="text" placeholder="Cerca Proprietari" class="form-control form-control-sm"></th> <th><input type="text" placeholder="Cerca Proprietari" class="form-control form-control-sm"></th>
<th><input type="text" placeholder="Cerca Città" class="form-control form-control-sm"></th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
@ -444,25 +469,17 @@ $result = $stmt->get_result();
<tr> <tr>
<!-- Thumbnail immagine --> <!-- Thumbnail immagine -->
<td> <td>
<img src="mainphoto/<?php echo htmlspecialchars($row['mainphoto'] ?? 'default.jpg'); ?>" <a href="manage-home.php?idhome=<?php echo $row['idhome']; ?>">
class="img-thumbnail open-photo" <img src="mainphoto/<?php echo htmlspecialchars($row['mainphoto'] ?? 'default.jpg'); ?>"
style="width: 80px; height: 80px; object-fit: cover; cursor: pointer;" class="img-thumbnail open-photo"
alt="<?php echo htmlspecialchars($row['name']); ?>" style="width: 80px; height: 80px; object-fit: cover; cursor: pointer;"
data-toggle="modal" data-target="#photoModal" alt="<?php echo htmlspecialchars($row['name']); ?>">
data-src="mainphoto/<?php echo htmlspecialchars($row['mainphoto'] ?? 'default.jpg'); ?>"> </a>
</td> </td>
<!-- Nome immobile --> <!-- Nome immobile -->
<td><?php echo htmlspecialchars($row['name']); ?></td> <td><?php echo htmlspecialchars($row['name']); ?></td>
<!-- Città e Nazione -->
<td><?php echo htmlspecialchars($row['city']); ?>, <?php echo htmlspecialchars($row['country']); ?></td>
<!-- Indirizzo -->
<td><?php echo htmlspecialchars($row['address']); ?></td>
<!-- Proprietari + Bottone --> <!-- Proprietari + Bottone -->
<td> <td>
<?php echo nl2br(htmlspecialchars($row['owner_names'])); ?> <?php echo nl2br(htmlspecialchars($row['owner_names'])); ?>
@ -485,7 +502,10 @@ $result = $stmt->get_result();
</a> </a>
</td> </td>
<!-- azioni --> <!-- Città e Nazione -->
<td><?php echo htmlspecialchars($row['city']); ?>, <?php echo htmlspecialchars($row['country']); ?></td>
<!-- Azioni -->
<td class="text-nowrap"> <td class="text-nowrap">
<div class="dropdown"> <div class="dropdown">
<button class="btn btn-light btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false"> <button class="btn btn-light btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
@ -510,12 +530,7 @@ $result = $stmt->get_result();
</ul> </ul>
</div> </div>
</td> </td>
</tr> </tr>
<?php } ?> <?php } ?>
</tbody> </tbody>
</table> </table>
@ -536,9 +551,12 @@ $result = $stmt->get_result();
while ($row = $result->fetch_assoc()) { ?> while ($row = $result->fetch_assoc()) { ?>
<div class="col-md-3 col-sm-6 mb-4"> <!-- 4 per riga su desktop, 2 su tablet --> <div class="col-md-3 col-sm-6 mb-4"> <!-- 4 per riga su desktop, 2 su tablet -->
<div class="card shadow-sm border-0 position-relative box-home"> <div class="card shadow-sm border-0 position-relative box-home">
<img src="mainphoto/<?php echo htmlspecialchars($row['mainphoto'] ?? 'default.jpg'); ?>" <a href="manage-home.php?idhome=<?php echo $row['idhome']; ?>">
class="card-img-top" <img src="mainphoto/<?php echo htmlspecialchars($row['mainphoto'] ?? 'default.jpg'); ?>"
alt="<?php echo htmlspecialchars($row['name']); ?>"> class="card-img-top"
alt="<?php echo htmlspecialchars($row['name']); ?>">
</a>
<!-- Pulsante 3 puntini --> <!-- Pulsante 3 puntini -->
<!-- Contenitore per i bottoni (Proprietari + Menu Azioni) --> <!-- Contenitore per i bottoni (Proprietari + Menu Azioni) -->

File diff suppressed because it is too large Load Diff

View File

@ -1,110 +1,141 @@
<?php include('include/headscript.php'); ?> <?php include('include/headscript.php'); ?>
<?php require_once 'class/db-functions.php'; ?>
<?php <?php
// Connessione al database // Inizializza la connessione al database con la classe DBHandlerSelect
$conn = new mysqli($servername, $username, $password, $database); $dbHandler = DBHandlerSelect::getInstance();
$pdo = $dbHandler->getConnection();
// Recupera l'id utente loggato e la sua email
$iduserlogin = $_SESSION['iduserlogin'];
$emailuser = $_SESSION['emailuser'];
// Verifica se si sta aggiungendo una nuova casa o aggiornando una esistente // Verifica se si sta aggiungendo una nuova casa o aggiornando una esistente
$idhome = isset($_GET['idhome']) ? intval($_GET['idhome']) : 0; $idhome = isset($_GET['idhome']) ? intval($_GET['idhome']) : 0;
$isNew = ($idhome == 0); $isNew = ($idhome == 0);
if ($isNew) { if ($isNew) {
// Se non esiste ancora l'idhome, crea un nuovo record e ricarica la pagina con l'ID generato // Inserisci un nuovo record
$insertQuery = $conn->prepare("INSERT INTO home (iduser) VALUES (?)"); $insertQuery = $pdo->prepare("INSERT INTO home (iduser) VALUES (:iduser)");
$insertQuery->bind_param("i", $iduserlogin); $insertQuery->execute(['iduser' => $iduserlogin]);
$insertQuery->execute(); $idhome = $pdo->lastInsertId();
$idhome = $conn->insert_id; // Ottieni il nuovo idhome generato
// Ricarica la pagina con il nuovo idhome // Ricarica la pagina con il nuovo idhome
header("Location: manage-home.php?idhome=$idhome"); header("Location: manage-home-tabs.php?idhome=$idhome");
exit(); // Assicurati di uscire per evitare che il codice continui
}
// Determina l'iduser corretto per l'immobile, controllando sia il proprietario che le condivisioni
$ownerId = null;
$queryOwner = $conn->prepare("SELECT iduser FROM home WHERE idhome = ?");
$queryOwner->bind_param("i", $idhome);
$queryOwner->execute();
$resultOwner = $queryOwner->get_result();
if ($resultOwner->num_rows > 0) {
$ownerData = $resultOwner->fetch_assoc();
$ownerId = $ownerData['iduser'];
}
// Verifica se l'utente ha accesso diretto (è il proprietario) o tramite condivisione
$hasAccess = false;
if ($ownerId == $iduserlogin) {
$hasAccess = true; // Utente è il proprietario
} else {
// Controlla se l'utente ha accesso tramite home_sharing
$querySharing = $conn->prepare("
SELECT * FROM home_sharing
WHERE idhome = ?
AND (idshareduser = ? OR shared_email = ?)
AND status = 'accepted'
");
$querySharing->bind_param("iis", $idhome, $iduserlogin, $emailuser);
$querySharing->execute();
$resultSharing = $querySharing->get_result();
$hasAccess = ($resultSharing->num_rows > 0);
}
// Se l'utente non ha accesso, reindirizza o mostra un errore
if (!$hasAccess) {
header("Location: access-denied.php"); // O una pagina di errore personalizzata
exit(); exit();
} }
// Carica i dati della casa per l'utente con accesso // Carica i dati della casa
$query = $conn->prepare("SELECT * FROM home WHERE idhome = ?"); $query = $pdo->prepare("SELECT * FROM home WHERE idhome = :idhome AND iduser = :iduser");
$query->bind_param("i", $idhome); $query->execute(['idhome' => $idhome, 'iduser' => $iduserlogin]);
$query->execute(); $homeData = $query->fetch();
$result = $query->get_result();
$homeData = $result->fetch_assoc();
// Assegna i valori esistenti ai campi // Assegna i valori
$namedb = $homeData['name']; $namedb = $homeData['name'] ?? '';
$addressdb = $homeData['address']; $addressdb = $homeData['address'] ?? '';
$countrydb = $homeData['country']; $countrydb = $homeData['country'] ?? '';
$citydb = $homeData['city']; $citydb = $homeData['city'] ?? '';
$zipdb = $homeData['zip']; $zipdb = $homeData['zip'] ?? '';
$commentdb = $homeData['comment']; $commentdb = $homeData['comment'] ?? '';
$latitudedb = $homeData['latitude']; $latitudedb = $homeData['latitude'] ?? '';
$longitudedb = $homeData['longitude']; $longitudedb = $homeData['longitude'] ?? '';
$fulladdressdb = $homeData['fulladdress']; $fulladdressdb = $homeData['fulladdress'] ?? '';
// Campi catastali $mainphoto = !empty($homeData['mainphoto']) ? 'mainphoto/' . $homeData['mainphoto'] : 'assets/images/no-image.jpg';
$cadastral_municipalitydb = $homeData['cadastral_municipality'];
$cadastral_sectiondb = $homeData['cadastral_section'];
$cadastral_sheetdb = $homeData['cadastral_sheet'];
$cadastral_particledb = $homeData['cadastral_particle'];
$cadastral_subdb = $homeData['cadastral_sub'];
$cadastral_categorydb = $homeData['cadastral_category'];
$cadastral_classdb = $homeData['cadastral_class'];
$cadastral_surfacedb = $homeData['cadastral_surface'];
$cadastral_renditadbs = $homeData['cadastral_rendita'];
$cadastral_notesdb = $homeData['cadastral_notes'];
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="it"> <html lang="it">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
<?php include('include/seo.php'); ?> <title>Gestione Immobile</title>
<link rel="shortcut icon" href="assets/images/favicon.ico">
<link href="assets/css/bootstrap.min.css" rel="stylesheet" type="text/css"> <link href="assets/css/bootstrap.min.css" rel="stylesheet" type="text/css">
<link href="assets/css/icons.css" rel="stylesheet" type="text/css"> <link href="assets/css/icons.css" rel="stylesheet" type="text/css">
<link href="assets/css/style.css" rel="stylesheet" type="text/css"> <link href="assets/css/style.css" rel="stylesheet" type="text/css">
<!-- Select2 CSS -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.1.0-rc.0/css/select2.min.css" rel="stylesheet" />
<link href="https://cdn.datatables.net/1.11.5/css/dataTables.bootstrap4.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.2/dropzone.min.css" rel="stylesheet">
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- Popper.js (necessario per Bootstrap) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<!-- Bootstrap JS -->
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<!-- SweetAlert2 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<!-- Select2 JS con fallback -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.1.0-rc.0/js/select2.min.js"></script>
<!-- DataTables JS -->
<script src="https://cdn.datatables.net/1.11.5/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.11.5/js/dataTables.bootstrap4.min.js"></script>
<!-- Dropzone JS -->
<script src="https://cdn.jsdelivr.net/npm/dropzone@5.9.2/dist/dropzone.min.js"></script>
<!-- MD5 JS -->
<script src="https://cdn.jsdelivr.net/npm/md5-js@0.0.3/md5.min.js"></script>
<script>
// Fallback per Select2
if (typeof $.fn.select2 === "undefined") {
document.write('<script src="assets/js/select2.min.js"><\/script>');
}
</script>
<style> <style>
/* Stile per il banner */
.header-banner-overlay {
position: relative;
width: 100%;
background: linear-gradient(to right, rgba(30, 58, 138, 0.8), rgba(255, 255, 255, 0.2));
padding: 20px;
display: flex;
align-items: center;
color: white;
border-radius: 10px;
margin-bottom: 20px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.header-banner-overlay img {
width: 80px;
height: 80px;
object-fit: cover;
border-radius: 8px;
margin-right: 20px;
border: 2px solid #fff;
}
.header-banner-overlay .property-info h2 {
font-size: 24px;
margin: 0;
font-weight: bold;
color: #ffffff;
/* Nome dell'immobile in bianco */
}
.header-banner-overlay .property-info p {
font-size: 14px;
margin: 5px 0 0;
opacity: 0.9;
}
.header-banner-overlay .property-info .status {
font-size: 12px;
background: #28a745;
padding: 5px 10px;
border-radius: 12px;
display: inline-block;
margin-top: 10px;
}
/* Stile per i tab */
.nav-tabs .nav-link {
font-weight: bold;
color: #495057;
}
.nav-tabs .nav-link.active {
color: #007bff;
border-color: #007bff;
}
#map { #map {
height: 400px; height: 400px;
width: 100%; width: 100%;
@ -120,20 +151,15 @@ $cadastral_notesdb = $homeData['cadastral_notes'];
<body class="fixed-left"> <body class="fixed-left">
<div id="wrapper"> <div id="wrapper">
<?php include('include/navigationbar.php'); ?> <?php include('include/navigationbar.php'); ?>
<div class="content-page"> <div class="content-page">
<div class="content"> <div class="content">
<?php include('include/topbar.php'); ?> <?php include('include/topbar.php'); ?>
<div class="page-content-wrapper"> <div class="page-content-wrapper">
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-12">
<div class="page-title-box d-flex justify-content-between align-items-center"> <div class="page-title-box d-flex justify-content-between align-items-center">
<!-- Titolo --> <h4 class="page-title m-0"><?php echo $isNew ? "Aggiungi Casa" : "Gestisci Casa"; ?></h4>
<h4 class="page-title m-0"><?php echo $isNew ? "Aggiungi Casa" : "Modifica Casa"; ?></h4>
<!-- Tasto Torna indietro -->
<button onclick="history.back()" class="btn btn-dark"> <button onclick="history.back()" class="btn btn-dark">
<i class="fas fa-arrow-left"></i> Torna indietro <i class="fas fa-arrow-left"></i> Torna indietro
</button> </button>
@ -141,453 +167,53 @@ $cadastral_notesdb = $homeData['cadastral_notes'];
</div> </div>
</div> </div>
<!-- Banner -->
<div class="row"> <div class="header-banner-overlay">
<div class="col-lg-12"> <img src="<?php echo htmlspecialchars($mainphoto); ?>" alt="Foto Immobile">
<div class="card"> <div class="property-info">
<div class="card-header bg-primary d-flex justify-content-between align-items-center"> <h2><?php echo htmlspecialchars($namedb ?: 'Nuovo Immobile'); ?></h2>
<h4 class="mb-0 text-white"><?php echo $isNew ? "Carta d'Identità dell'Immobile" : "Dettagli dell'Immobile"; ?></h4> <p><?php echo htmlspecialchars($fulladdressdb ?: 'Indirizzo non specificato'); ?></p>
<button id="edit-toggle" class="btn btn-light btn-sm"> <span class="status"><?php echo $isNew ? 'Nuovo' : 'Attivo'; ?></span>
<i class="fas fa-pencil-alt"></i> Modifica
</button>
</div>
<div class="card-body">
<form id="home-form">
<input type="hidden" name="idhome" value="<?php echo $idhome; ?>">
<!-- Sezione Nome e Foto -->
<div class="row">
<div class="col-md-8">
<div class="form-group">
<label>Nome Immobile</label>
<input type="text" value="<?php echo htmlspecialchars($namedb); ?>" id="name" name="name" class="form-control form-field" readonly>
</div>
<!-- Sezione Note -->
<div class="form-group">
<h5 class="text-primary"><i class="fas fa-sticky-note"></i> Note</h5>
<textarea id="comment" name="comment" rows="3" class="form-control form-field" readonly><?php echo htmlspecialchars($commentdb); ?></textarea>
</div>
</div>
<div class="col-md-4 text-center">
<label>Foto dell'Immobile</label>
<div class="photo-container">
<input type="file" id="photo" name="photo" class="form-control form-field d-none" accept="image/*" disabled>
<img id="photo-preview" src="<?php echo !empty($homeData['mainphoto']) ? 'mainphoto/' . $homeData['mainphoto'] : 'assets/images/no-image.jpg'; ?>" alt="Anteprima Foto" class="img-fluid mt-2 rounded shadow" style="max-width: 200px;">
</div>
<small class="text-muted photo-hint d-none">Carica un'unica foto, verrà sovrascritta se ne scegli un'altra.</small>
</div>
</div>
<!-- Sezione Indirizzo -->
<div class="border rounded p-3 mt-4">
<h5 class="text-primary"><i class="fas fa-map-marker-alt"></i> Indirizzo</h5>
<label>Indirizzo Completo</label>
<input type="text" value="<?php echo htmlspecialchars($fulladdressdb); ?>" id="fulladdress" name="fulladdress" class="form-control form-field" readonly>
<div id="map" class="mt-3" style="height: 300px;"></div>
</div>
<!-- Sezione Dati Catastali -->
<div class="border rounded p-3 mt-4">
<h5 class="text-primary"><i class="fas fa-building"></i> Dati Catastali</h5>
<div class="row">
<div class="col-md-4">
<label>Comune Catastale</label>
<input type="text" value="<?php echo htmlspecialchars($cadastral_municipalitydb); ?>" id="cadastral_municipality" name="cadastral_municipality" class="form-control form-field" readonly>
</div>
<div class="col-md-4">
<label>Sezione</label>
<input type="text" value="<?php echo htmlspecialchars($cadastral_sectiondb); ?>" id="cadastral_section" name="cadastral_section" class="form-control form-field" readonly>
</div>
<div class="col-md-4">
<label>Foglio</label>
<input type="text" value="<?php echo htmlspecialchars($cadastral_sheetdb); ?>" id="cadastral_sheet" name="cadastral_sheet" class="form-control form-field" readonly>
</div>
</div>
<div class="row mt-2">
<div class="col-md-4">
<label>Particella</label>
<input type="text" value="<?php echo htmlspecialchars($cadastral_particledb); ?>" id="cadastral_particle" name="cadastral_particle" class="form-control form-field" readonly>
</div>
<div class="col-md-4">
<label>Subalterno</label>
<input type="text" value="<?php echo htmlspecialchars($cadastral_subdb); ?>" id="cadastral_sub" name="cadastral_sub" class="form-control form-field" readonly>
</div>
<div class="col-md-4">
<label>Categoria Catastale</label>
<input type="text" value="<?php echo htmlspecialchars($cadastral_categorydb); ?>" id="cadastral_category" name="cadastral_category" class="form-control form-field" readonly>
</div>
</div>
<div class="row mt-2">
<div class="col-md-4">
<label>Classe Catastale</label>
<input type="text" value="<?php echo htmlspecialchars($cadastral_classdb); ?>" id="cadastral_class" name="cadastral_class" class="form-control form-field" readonly>
</div>
<div class="col-md-4">
<label>Superficie (mq)</label>
<input type="number" step="0.01" value="<?php echo htmlspecialchars($cadastral_surfacedb); ?>" id="cadastral_surface" name="cadastral_surface" class="form-control form-field" readonly>
</div>
<div class="col-md-4">
<label>Rendita ()</label>
<input type="number" step="0.01" value="<?php echo htmlspecialchars($cadastral_renditadbs); ?>" id="cadastral_rendita" name="cadastral_rendita" class="form-control form-field" readonly>
</div>
</div>
</div>
<!-- Sezione Geolocalizzazione (campi nascosti) -->
<div class="row mt-3">
<div class="col-md-6">
<input type="hidden" id="latitude" name="latitude" value="<?php echo htmlspecialchars($latitudedb); ?>">
</div>
<div class="col-md-6">
<input type="hidden" id="longitude" name="longitude" value="<?php echo htmlspecialchars($longitudedb); ?>">
</div>
<div class="col-md-4">
<input type="hidden" id="zip" name="zip" value="<?php echo htmlspecialchars($zipdb); ?>">
</div>
<div class="col-md-4">
<input type="hidden" id="city" name="city" value="<?php echo htmlspecialchars($citydb); ?>">
</div>
<div class="col-md-4">
<input type="hidden" id="country" name="country" value="<?php echo htmlspecialchars($countrydb); ?>">
</div>
</div>
<!-- <button type="submit" class="btn btn-primary mt-3 w-100 save-btn d-none"><i class="fas fa-save"></i> Salva</button> -->
</form>
</div>
</div>
</div> </div>
</div> </div>
<!-- Aggiungi il seguente script JavaScript --> <!-- Tab Navigation -->
<script> <ul class="nav nav-tabs" id="propertyTabs" role="tablist">
document.addEventListener('DOMContentLoaded', function() { <li class="nav-item">
const editToggleBtn = document.getElementById('edit-toggle'); <a class="nav-link active" id="details-tab" data-toggle="tab" href="#details" role="tab" aria-controls="details" aria-selected="true">Dettagli</a>
const formFields = document.querySelectorAll('.form-field'); </li>
const saveBtn = document.querySelector('.save-btn'); <li class="nav-item">
const photoInput = document.getElementById('photo'); <a class="nav-link" id="documents-tab" data-toggle="tab" href="#documents" role="tab" aria-controls="documents" aria-selected="false">Documenti</a>
const photoHint = document.querySelector('.photo-hint'); </li>
<li class="nav-item">
<a class="nav-link" id="owners-tab" data-toggle="tab" href="#owners" role="tab" aria-controls="owners" aria-selected="false">Proprietari</a>
</li>
</ul>
// Ottieni il valore di isNew dalla pagina PHP <!-- Tab Content -->
const isNewRecord = <?php echo $isNew ? 'true' : 'false'; ?>; <div class="tab-content" id="propertyTabsContent">
<!-- Tab Dettagli -->
// Variabile per tenere traccia dello stato di modifica <div class="tab-pane fade show active" id="details" role="tabpanel" aria-labelledby="details-tab">
let editMode = isNewRecord; <?php include('tabs/dettagli.php'); ?>
</div>
// Se è un nuovo record, entra automaticamente in modalità modifica <!-- Tab Documenti -->
if (isNewRecord) { <div class="tab-pane fade" id="documents" role="tabpanel" aria-labelledby="documents-tab">
// Modifica il testo del pulsante <?php include('tabs/documenti.php'); ?>
editToggleBtn.innerHTML = '<i class="fas fa-save"></i> Salva'; </div>
editToggleBtn.classList.remove('btn-light'); <!-- Tab Proprietari -->
editToggleBtn.classList.add('btn-info'); <div class="tab-pane fade" id="owners" role="tabpanel" aria-labelledby="owners-tab">
<?php include('tabs/proprietari.php'); ?>
// Abilita tutti i campi </div>
formFields.forEach(field => { </div>
field.readOnly = false; </div>
field.disabled = false; </div>
if (field.type === 'file') { </div>
field.classList.remove('d-none');
}
});
// Mostra pulsante salva e suggerimento foto
saveBtn.classList.remove('d-none');
photoHint.classList.remove('d-none');
}
// Gestione del click sul pulsante di modifica
editToggleBtn.addEventListener('click', function() {
editMode = !editMode;
if (editMode) {
// Attiva modalità modifica
editToggleBtn.innerHTML = '<i class="fas fa-save"></i> Salva';
editToggleBtn.classList.remove('btn-light');
editToggleBtn.classList.add('btn-success');
// Abilita tutti i campi
formFields.forEach(field => {
field.readOnly = false;
field.disabled = false;
if (field.type === 'file') {
field.classList.remove('d-none');
}
});
// Mostra pulsante salva e suggerimento foto
saveBtn.classList.remove('d-none');
photoHint.classList.remove('d-none');
} else {
// Torna alla modalità visualizzazione
editToggleBtn.innerHTML = '<i class="fas fa-pencil-alt"></i> Modifica';
editToggleBtn.classList.remove('btn-info');
editToggleBtn.classList.add('btn-light');
// Disabilita tutti i campi
formFields.forEach(field => {
field.readOnly = true;
field.disabled = true;
if (field.type === 'file') {
field.classList.add('d-none');
}
});
// Nascondi pulsante salva e suggerimento foto
saveBtn.classList.add('d-none');
photoHint.classList.add('d-none');
}
});
});
</script>
<script>
// Caricamento della mappa
function initMap() {
let map = new google.maps.Map(document.getElementById("map"), {
center: {
lat: 41.9028,
lng: 12.4964
}, // Roma
zoom: 14
});
let marker = new google.maps.Marker({
position: {
lat: 41.9028,
lng: 12.4964
},
map: map,
draggable: true
});
marker.addListener("dragend", function() {
let position = marker.getPosition();
document.getElementById("latitude").value = position.lat();
document.getElementById("longitude").value = position.lng();
});
}
// Cambio immagine al clic sulla foto
document.getElementById("photo-preview").addEventListener("click", function() {
document.getElementById("photo").click();
});
// Anteprima immagine selezionata
document.getElementById('photo').addEventListener('change', function(event) {
let file = event.target.files[0];
if (!file) return;
let formData = new FormData();
formData.append("photo", file);
formData.append("idhome", <?php echo $idhome; ?>);
let xhr = new XMLHttpRequest();
xhr.open("POST", "save-home.php", true);
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
let response = JSON.parse(xhr.responseText);
if (response.success) {
document.getElementById('photo-preview').src = "mainphoto/" + response.filename;
} else {
alert("Errore nel caricamento: " + response.message);
}
}
};
xhr.send(formData);
});
</script>
<!-- Inclusione API Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?key=TUACHIAVEAPI&callback=initMap" async defer></script>
</div><!-- container -->
</div> <!-- Page content Wrapper -->
</div> <!-- content -->
<?php include('include/footer.php'); ?> <?php include('include/footer.php'); ?>
</div> </div>
</div> </div>
<!-- Google Maps API for Autocomplete and Geolocation --> <!-- Google Maps API -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyADtQRKgCpJNnQCP8QvBeKDcm0TrTPpsGY&libraries=places&callback=initAutocomplete"></script> <script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyADtQRKgCpJNnQCP8QvBeKDcm0TrTPpsGY&libraries=places&callback=initAutocomplete"></script>
<script>
let map, marker, autocomplete;
// Funzione per inviare i dati del campo tramite AJAX
function updateField(field, value, additionalData = {}) {
const idhome = <?php echo $idhome; ?>;
const inputField = document.getElementById(field);
var xhr = new XMLHttpRequest();
xhr.open("POST", "save-home.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
inputField.classList.add("success-flash");
setTimeout(function() {
inputField.classList.remove("success-flash");
}, 1000);
} else {
console.error("Errore durante l'aggiornamento: " + xhr.responseText);
}
}
};
let params = `field=${encodeURIComponent(field)}&value=${encodeURIComponent(value)}&idhome=${idhome}`;
for (let key in additionalData) {
params += `&${key}=${encodeURIComponent(additionalData[key])}`;
}
xhr.send(params);
}
// Funzione per la mappa e autocomplete
function initAutocomplete() {
const latitude = parseFloat(document.getElementById('latitude').value);
const longitude = parseFloat(document.getElementById('longitude').value);
const defaultLocation = {
lat: 41.9028,
lng: 12.4964
}; // Default: Roma
const location = !isNaN(latitude) && !isNaN(longitude) ? {
lat: latitude,
lng: longitude
} : defaultLocation;
// Inizializza la mappa
map = new google.maps.Map(document.getElementById('map'), {
center: location,
zoom: 14
});
// Aggiungi un marker
marker = new google.maps.Marker({
position: location,
map: map,
draggable: true
});
google.maps.event.addListener(marker, 'dragend', function() {
const position = marker.getPosition();
document.getElementById('latitude').value = position.lat();
document.getElementById('longitude').value = position.lng();
// Aggiorna latitudine e longitudine
updateField('latitude', position.lat());
updateField('longitude', position.lng());
});
// Autocomplete per l'indirizzo
autocomplete = new google.maps.places.Autocomplete(document.getElementById('fulladdress'), {
types: ['geocode']
});
autocomplete.addListener('place_changed', fillInAddress);
}
// Riempie i campi dopo che un indirizzo è stato selezionato
function fillInAddress() {
const place = autocomplete.getPlace();
if (!place.geometry) {
console.error("Errore: Il luogo selezionato non contiene informazioni di geolocalizzazione.");
return;
}
const location = place.geometry.location;
// Controlla se gli elementi esistono prima di impostare i valori
if (document.getElementById('latitude')) {
document.getElementById('latitude').value = location.lat();
}
if (document.getElementById('longitude')) {
document.getElementById('longitude').value = location.lng();
}
const addressComponents = place.address_components;
let zip = "",
city = "",
country = "",
address = "";
addressComponents.forEach(component => {
const types = component.types;
if (types.includes("postal_code")) zip = component.long_name;
if (types.includes("locality")) city = component.long_name;
if (types.includes("country")) country = component.long_name;
if (types.includes("street_number") || types.includes("route")) {
address += component.long_name + " ";
}
});
if (document.getElementById('zip')) {
document.getElementById('zip').value = zip;
}
if (document.getElementById('city')) {
document.getElementById('city').value = city;
}
if (document.getElementById('country')) {
document.getElementById('country').value = country;
}
if (document.getElementById('address')) {
document.getElementById('address').value = address.trim();
}
if (document.getElementById('fulladdress')) {
document.getElementById('fulladdress').value = place.formatted_address;
}
// Centra la mappa e sposta il marker
if (map && marker) {
map.setCenter(location);
marker.setPosition(location);
} else {
console.error("Errore: Mappa o Marker non inizializzati correttamente.");
}
// Aggiorna i campi tramite AJAX
updateField('fulladdress', place.formatted_address, {
address: address.trim(),
zip: zip,
city: city,
country: country,
latitude: location.lat(),
longitude: location.lng()
});
}
// Event listener per aggiornamento automatico dei dati al cambio di valore
const fieldsToUpdate = [
'name', 'comment', 'cadastral_municipality', 'cadastral_section', 'cadastral_sheet',
'cadastral_particle', 'cadastral_sub', 'cadastral_category', 'cadastral_class',
'cadastral_surface', 'cadastral_rendita', 'cadastral_notes'
];
fieldsToUpdate.forEach(field => {
const inputField = document.getElementById(field);
if (inputField) {
inputField.addEventListener('change', function() {
updateField(field, this.value);
});
}
});
</script>
<!-- jQuery -->
<script src="assets/js/jquery.min.js"></script>
<script src="assets/js/popper.min.js"></script>
<script src="assets/js/bootstrap.min.js"></script>
</body> </body>
</html> </html>

View File

@ -3,18 +3,13 @@ ini_set('display_errors', 1);
ini_set('display_startup_errors', 1); ini_set('display_startup_errors', 1);
error_reporting(E_ALL); error_reporting(E_ALL);
include('include/headscript.php'); require_once __DIR__ . '/class/db-functions.php';
$dbHandler = DBHandlerSelect::getInstance();
// Connessione al database $pdo = $dbHandler->getConnection();
$conn = new mysqli($servername, $username, $password, $database);
if ($conn->connect_error) {
die("Errore di connessione: " . $conn->connect_error);
}
// Recupera i dati inviati tramite POST // Recupera i dati inviati tramite POST
$idhome = isset($_POST['idhome']) ? intval($_POST['idhome']) : 0; $idhome = isset($_POST['idhome']) ? (int)$_POST['idhome'] : 0;
$owner_id = isset($_POST['owner_id']) ? intval($_POST['owner_id']) : 0; $owner_id = isset($_POST['owner_id']) ? (int)$_POST['owner_id'] : 0;
// Verifica che tutti i dati necessari siano presenti // Verifica che tutti i dati necessari siano presenti
if ($idhome <= 0 || $owner_id <= 0) { if ($idhome <= 0 || $owner_id <= 0) {
@ -23,19 +18,14 @@ if ($idhome <= 0 || $owner_id <= 0) {
} }
// Elimina il proprietario dalla tabella home_owners // Elimina il proprietario dalla tabella home_owners
$queryDelete = $conn->prepare("DELETE FROM home_owners WHERE home_id = ? AND owner_id = ?"); $stmt = $pdo->prepare("DELETE FROM home_owners WHERE home_id = ? AND owner_id = ?");
if ($queryDelete === false) { try {
echo json_encode(['success' => false, 'message' => 'Errore nella preparazione della query.']); $stmt->execute([$idhome, $owner_id]);
exit; if ($stmt->rowCount() > 0) {
echo json_encode(['success' => true, 'message' => 'Proprietario rimosso con successo.']);
} else {
echo json_encode(['success' => false, 'message' => 'Proprietario non trovato o già rimosso.']);
}
} catch (PDOException $e) {
echo json_encode(['success' => false, 'message' => 'Errore nella rimozione del proprietario: ' . $e->getMessage()]);
} }
$queryDelete->bind_param('ii', $idhome, $owner_id);
if ($queryDelete->execute()) {
echo json_encode(['success' => true, 'message' => 'Proprietario rimosso con successo.']);
} else {
echo json_encode(['success' => false, 'message' => 'Errore nella rimozione del proprietario.']);
}
$queryDelete->close();
$conn->close();

View File

@ -44,72 +44,75 @@ if (!empty($_FILES['photo']) && isset($_POST['idhome'])) {
exit(); exit();
} }
// Aggiornamento AJAX degli altri campi // Aggiornamento di tutti i campi inviati
$idhome = isset($_POST['idhome']) ? intval($_POST['idhome']) : 0; if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['idhome'])) {
$field = isset($_POST['field']) ? $conn->real_escape_string($_POST['field']) : ''; $idhome = intval($_POST['idhome']);
$value = isset($_POST['value']) ? $conn->real_escape_string($_POST['value']) : '';
// Lista dei campi consentiti per la sicurezza // Lista dei campi consentiti
$allowedFields = [ $allowedFields = [
'name', 'name',
'comment', 'comment',
'fulladdress', 'fulladdress',
'address', 'address',
'zip', 'zip',
'city', 'city',
'country', 'country',
'latitude', 'latitude',
'longitude', 'longitude',
'cadastral_municipality', 'cadastral_municipality',
'cadastral_section', 'cadastral_section',
'cadastral_sheet', 'cadastral_sheet',
'cadastral_particle', 'cadastral_particle',
'cadastral_sub', 'cadastral_sub',
'cadastral_category', 'cadastral_category',
'cadastral_class', 'cadastral_class',
'cadastral_surface', 'cadastral_surface',
'cadastral_rendita', 'cadastral_rendita',
'cadastral_notes' 'cadastral_notes'
]; ];
// Se il campo non è nella lista, termina lo script per evitare SQL Injection $updates = [];
if (!in_array($field, $allowedFields)) { $values = [];
die(json_encode(['success' => false, 'message' => "Campo non valido."])); $types = '';
}
// Se è l'aggiornamento dell'indirizzo completo, aggiorniamo tutti i relativi campi // Raccogli i campi da aggiornare
if ($field == 'fulladdress') { foreach ($_POST as $key => $value) {
$address = isset($_POST['address']) ? $conn->real_escape_string($_POST['address']) : ''; if (in_array($key, $allowedFields)) {
$city = isset($_POST['city']) ? $conn->real_escape_string($_POST['city']) : ''; $updates[] = "$key = ?";
$zip = isset($_POST['zip']) ? $conn->real_escape_string($_POST['zip']) : ''; $values[] = $conn->real_escape_string($value);
$country = isset($_POST['country']) ? $conn->real_escape_string($_POST['country']) : ''; $types .= 's'; // Tutti i valori sono trattati come stringhe per semplicità
$latitude = isset($_POST['latitude']) ? $conn->real_escape_string($_POST['latitude']) : ''; }
$longitude = isset($_POST['longitude']) ? $conn->real_escape_string($_POST['longitude']) : ''; }
error_log("Aggiornamento indirizzo: fulladdress=$value, address=$address, city=$city, zip=$zip, country=$country, latitude=$latitude, longitude=$longitude, idhome=$idhome"); if (empty($updates)) {
echo json_encode(['success' => false, 'message' => "Nessun campo valido da aggiornare."]);
exit();
}
$query = "UPDATE home SET fulladdress = ?, address = ?, city = ?, zip = ?, country = ?, latitude = ?, longitude = ? WHERE idhome = ?"; // Aggiungi idhome per la WHERE clause
$values[] = $idhome;
$types .= 'i';
// Costruisci la query
$query = "UPDATE home SET " . implode(', ', $updates) . " WHERE idhome = ?";
$stmt = $conn->prepare($query); $stmt = $conn->prepare($query);
if ($stmt === false) { if ($stmt === false) {
die(json_encode(['success' => false, 'message' => "Errore nella preparazione della query: " . $conn->error])); die(json_encode(['success' => false, 'message' => "Errore nella preparazione della query: " . $conn->error]));
} }
$stmt->bind_param("sssssssi", $value, $address, $city, $zip, $country, $latitude, $longitude, $idhome);
} else { // Bind dinamico dei parametri
// Aggiornamento di qualsiasi altro campo $stmt->bind_param($types, ...$values);
$query = "UPDATE home SET $field = ? WHERE idhome = ?";
$stmt = $conn->prepare($query); // Esegui la query
if ($stmt === false) { if ($stmt->execute()) {
die(json_encode(['success' => false, 'message' => "Errore nella preparazione della query: " . $conn->error])); echo json_encode(['success' => true, 'message' => 'Aggiornamento riuscito']);
} else {
echo json_encode(['success' => false, 'message' => 'Errore: ' . $stmt->error]);
} }
$stmt->bind_param("si", $value, $idhome);
}
// Esegui la query $stmt->close();
if ($stmt->execute()) {
echo json_encode(['success' => true, 'message' => 'Aggiornamento riuscito']);
} else { } else {
echo json_encode(['success' => false, 'message' => 'Errore: ' . $stmt->error]); echo json_encode(['success' => false, 'message' => "Richiesta non valida."]);
} }
$stmt->close();
$conn->close(); $conn->close();

View File

@ -0,0 +1,375 @@
<?php
global $idhome, $isNew, $homeData, $namedb, $addressdb, $countrydb, $citydb, $zipdb, $commentdb, $latitudedb, $longitudedb, $fulladdressdb,
$cadastral_municipalitydb, $cadastral_sectiondb, $cadastral_sheetdb, $cadastral_particledb, $cadastral_subdb, $cadastral_categorydb,
$cadastral_classdb, $cadastral_surfacedb, $cadastral_renditadb;
require_once dirname(__DIR__) . '/class/db-functions.php';
$dbHandler = DBHandlerSelect::getInstance();
$pdo = $dbHandler->getConnection();
?>
<style>
/* Stile per l'overlay dello spinner */
.loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 9999;
display: none;
}
.loading-overlay .spinner-custom {
width: 4rem;
height: 4rem;
border: 4px solid #fff;
border-top: 4px solid #007bff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
.loading-overlay .spinner-text {
color: #fff;
font-size: 1.2rem;
margin-top: 1rem;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
<div class="card card-body">
<!-- Overlay dello spinner -->
<div id="loading-overlay" class="loading-overlay">
<div class="spinner-custom"></div>
<div class="spinner-text">Salvataggio Dati...</div>
</div>
<h4 class="card-title font-20 mt-0"><?php echo $isNew ? "Aggiungi una nuova casa" : "Modifica la tua casa"; ?></h4>
<!-- Tasto Salva in cima -->
<div class="d-flex justify-content-between align-items-center mb-3">
<button type="button" id="save-form-btn" class="btn btn-primary">
<i class="fas fa-save"></i> Salva Modifiche
</button>
<div id="save-message" class="alert d-none" role="alert"></div>
</div>
<form id="home-form">
<input type="hidden" name="idhome" value="<?php echo $idhome; ?>">
<!-- Sezione Dati Principali -->
<h4 class="mt-4">Dati Principali</h4>
<div class="form-group">
<label>Nome</label>
<input type="text" value="<?php echo htmlspecialchars($namedb); ?>" id="name" name="name" class="form-control" required>
</div>
<div class="form-group">
<label>Nota</label>
<textarea id="comment" name="comment" rows="4" class="form-control"><?php echo htmlspecialchars($commentdb); ?></textarea>
</div>
<h4 class="mt-4">Indirizzo</h4>
<div class="form-group">
<label>Indirizzo Completo</label>
<input type="text" value="<?php echo htmlspecialchars($fulladdressdb); ?>" id="fulladdress" name="fulladdress" class="form-control">
</div>
<!-- Sezione Mappa e Foto -->
<div class="row mt-4">
<div class="col-md-6 mb-3">
<h5>Geolocalizzazione</h5>
<div id="map" style="height: 200px; width: 100%; border-radius: 8px; border: 1px solid #ddd;"></div>
</div>
<div class="col-md-6 mb-3">
<h5>Foto dell'immobile</h5>
<div class="form-group">
<label for="photo">Carica Foto</label>
<input type="file" id="photo" name="photo" class="form-control" accept="image/*">
<small class="text-muted">Carica un'unica foto, verrà sovrascritta se ne scegli un'altra.</small>
</div>
<div class="form-group">
<img id="photo-preview" src="<?php echo !empty($homeData['mainphoto']) ? 'mainphoto/' . $homeData['mainphoto'] : 'assets/images/no-image.jpg'; ?>" alt="Anteprima Foto" style="max-width: 100%; height: 200px; object-fit: cover; border-radius: 8px; border: 1px solid #ddd;">
</div>
</div>
</div>
<!-- Sezione Dati Catastali -->
<h4 class="mt-4">Dati Catastali (opzionali)</h4>
<p class="text-muted mb-3">Questi campi non sono obbligatori e possono essere lasciati vuoti.</p>
<h5>Identificativi Catastali</h5>
<div class="row">
<div class="col-md-6 form-group">
<label>Comune Catastale</label>
<input type="text" id="cadastral_municipality" name="cadastral_municipality" value="<?php echo htmlspecialchars($cadastral_municipalitydb); ?>" class="form-control">
</div>
<div class="col-md-6 form-group">
<label>Sezione Catastale</label>
<input type="text" id="cadastral_section" name="cadastral_section" value="<?php echo htmlspecialchars($cadastral_sectiondb); ?>" class="form-control">
</div>
</div>
<div class="row">
<div class="col-md-6 form-group">
<label>Foglio Catastale</label>
<input type="text" id="cadastral_sheet" name="cadastral_sheet" value="<?php echo htmlspecialchars($cadastral_sheetdb); ?>" class="form-control">
</div>
<div class="col-md-6 form-group">
<label>Particella Catastale</label>
<input type="text" id="cadastral_particle" name="cadastral_particle" value="<?php echo htmlspecialchars($cadastral_particledb); ?>" class="form-control">
</div>
</div>
<div class="row">
<div class="col-md-6 form-group">
<label>Subalterno Catastale</label>
<input type="text" id="cadastral_sub" name="cadastral_sub" value="<?php echo htmlspecialchars($cadastral_subdb); ?>" class="form-control">
</div>
</div>
<h5 class="mt-3">Caratteristiche Catastali</h5>
<div class="row">
<div class="col-md-6 form-group">
<label>Categoria Catastale</label>
<input type="text" id="cadastral_category" name="cadastral_category" value="<?php echo htmlspecialchars($cadastral_categorydb); ?>" class="form-control">
</div>
<div class="col-md-6 form-group">
<label>Classe Catastale</label>
<input type="text" id="cadastral_class" name="cadastral_class" value="<?php echo htmlspecialchars($cadastral_classdb); ?>" class="form-control">
</div>
</div>
<div class="row">
<div class="col-md-6 form-group">
<label>Superficie Catastale ()</label>
<input type="number" step="0.01" id="cadastral_surface" name="cadastral_surface" value="<?php echo htmlspecialchars($cadastral_surfacedb); ?>" class="form-control">
</div>
<div class="col-md-6 form-group">
<label>Rendita Catastale ()</label>
<input type="text" id="cadastral_rendita" name="cadastral_rendita" value="<?php echo htmlspecialchars($cadastral_renditadb); ?>" class="form-control">
</div>
</div>
<!-- Sezione Dettagli Indirizzo -->
<h4 class="mt-4">Dettagli Indirizzo</h4>
<div class="row">
<div class="col-md-6 form-group">
<label>CAP</label>
<input type="text" id="zip" name="zip" value="<?php echo htmlspecialchars($zipdb); ?>" class="form-control" readonly>
</div>
<div class="col-md-6 form-group">
<label>Città</label>
<input type="text" id="city" name="city" value="<?php echo htmlspecialchars($citydb); ?>" class="form-control" readonly>
</div>
</div>
<div class="row">
<div class="col-md-6 form-group">
<label>Nazione</label>
<input type="text" id="country" name="country" value="<?php echo htmlspecialchars($countrydb); ?>" class="form-control" readonly>
</div>
</div>
<div class="row">
<div class="col-md-6 form-group">
<label>Latitudine</label>
<input type="text" id="latitude" name="latitude" value="<?php echo htmlspecialchars($latitudedb); ?>" class="form-control" readonly>
</div>
<div class="col-md-6 form-group">
<label>Longitudine</label>
<input type="text" id="longitude" name="longitude" value="<?php echo htmlspecialchars($longitudedb); ?>" class="form-control" readonly>
</div>
</div>
</form>
</div>
<script>
// Gestione caricamento foto
document.getElementById('photo').addEventListener('change', function(event) {
let file = event.target.files[0];
if (!file) return;
const loadingOverlay = document.getElementById('loading-overlay');
loadingOverlay.style.display = 'flex';
let formData = new FormData();
formData.append("photo", file);
formData.append("idhome", <?php echo $idhome; ?>);
let xhr = new XMLHttpRequest();
xhr.open("POST", "save-home.php", true);
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
loadingOverlay.style.display = 'none';
let response = JSON.parse(xhr.responseText);
if (response.success) {
document.getElementById('photo-preview').src = "mainphoto/" + response.filename;
showSaveMessage("Foto caricata con successo!", "success");
} else {
showSaveMessage("Errore nel caricamento della foto: " + response.message, "danger");
}
}
};
xhr.send(formData);
});
// Funzione per mostrare il messaggio di salvataggio
function showSaveMessage(message, type) {
const saveMessage = document.getElementById('save-message');
saveMessage.className = `alert alert-${type} d-block`;
saveMessage.textContent = message;
setTimeout(() => {
saveMessage.className = 'alert d-none';
}, 3000);
}
// Gestione tasto Salva con spinner
document.getElementById('save-form-btn').addEventListener('click', function() {
const loadingOverlay = document.getElementById('loading-overlay');
loadingOverlay.style.display = 'flex';
this.disabled = true;
const form = document.getElementById('home-form');
const fields = [
'name', 'comment', 'fulladdress',
'cadastral_municipality', 'cadastral_section', 'cadastral_sheet', 'cadastral_particle', 'cadastral_sub',
'cadastral_category', 'cadastral_class', 'cadastral_surface', 'cadastral_rendita',
'latitude', 'longitude', 'zip', 'city', 'country', 'address'
];
// Raccogli i dati del form
let params = `idhome=${encodeURIComponent(<?php echo $idhome; ?>)}`;
fields.forEach(field => {
const value = document.getElementById(field)?.value || '';
params += `&${field}=${encodeURIComponent(value)}`;
});
// Invia i dati tramite AJAX
const xhr = new XMLHttpRequest();
xhr.open("POST", "save-home.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
loadingOverlay.style.display = 'none';
document.getElementById('save-form-btn').disabled = false;
if (xhr.status === 200) {
let response;
try {
response = JSON.parse(xhr.responseText);
} catch (e) {
showSaveMessage("Errore: Risposta non valida dal server.", "danger");
return;
}
if (response.success) {
showSaveMessage("Modifiche salvate con successo!", "success");
} else {
showSaveMessage("Errore durante il salvataggio: " + response.message, "danger");
}
} else {
showSaveMessage("Errore di connessione: " + xhr.statusText, "danger");
}
}
};
xhr.send(params);
});
// Gestione mappa
let map, marker, autocomplete;
function initAutocomplete() {
const latitude = parseFloat(document.getElementById('latitude').value);
const longitude = parseFloat(document.getElementById('longitude').value);
const defaultLocation = {
lat: 41.9028,
lng: 12.4964
};
const location = !isNaN(latitude) && !isNaN(longitude) ? {
lat: latitude,
lng: longitude
} : defaultLocation;
map = new google.maps.Map(document.getElementById('map'), {
center: location,
zoom: 14
});
marker = new google.maps.Marker({
position: location,
map: map,
draggable: true
});
google.maps.event.addListener(marker, 'dragend', function() {
const position = marker.getPosition();
document.getElementById('latitude').value = position.lat();
document.getElementById('longitude').value = position.lng();
});
autocomplete = new google.maps.places.Autocomplete(document.getElementById('fulladdress'), {
types: ['geocode']
});
autocomplete.addListener('place_changed', fillInAddress);
}
function fillInAddress() {
const place = autocomplete.getPlace();
if (!place.geometry) {
console.error("Errore: Il luogo selezionato non contiene informazioni di geolocalizzazione.");
return;
}
const location = place.geometry.location;
if (document.getElementById('latitude')) {
document.getElementById('latitude').value = location.lat();
}
if (document.getElementById('longitude')) {
document.getElementById('longitude').value = location.lng();
}
const addressComponents = place.address_components;
let zip = "",
city = "",
country = "",
address = "";
addressComponents.forEach(component => {
const types = component.types;
if (types.includes("postal_code")) zip = component.long_name;
if (types.includes("locality")) city = component.long_name;
if (types.includes("country")) country = component.long_name;
if (types.includes("street_number") || types.includes("route")) {
address += component.long_name + " ";
}
});
if (document.getElementById('zip')) {
document.getElementById('zip').value = zip;
}
if (document.getElementById('city')) {
document.getElementById('city').value = city;
}
if (document.getElementById('country')) {
document.getElementById('country').value = country;
}
if (document.getElementById('address')) {
document.getElementById('address').value = address.trim();
}
map.setCenter(location);
marker.setPosition(location);
}
</script>

View File

@ -0,0 +1,697 @@
<?php
// Assicurati che idhome sia passato
if (!isset($idhome) || $idhome <= 0) {
die("Errore: ID immobile non valido.");
}
// Recupera i dettagli della casa
$stmt = $pdo->prepare("SELECT name, address, zip, city, country FROM home WHERE idhome = ? AND iduser = ?");
$stmt->execute([$idhome, $iduserlogin]);
$homeData = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$homeData) {
die("Errore: Casa non trovata o accesso non autorizzato.");
}
// Recupera le pagine disponibili nella tabella 'pages'
$stmt = $pdo->query("SELECT * FROM pages ORDER BY namepages");
$pages = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$pages[] = $row;
}
// Imposta lo slug predefinito
$docpage = isset($_GET['docpage']) ? $_GET['docpage'] : 'legal';
?>
<!-- Contenuto del tab Documenti -->
<div class="tab-pane fade show active" id="documenti" role="tabpanel" aria-labelledby="documenti-tab">
<div class="card">
<div class="card-body">
<!-- Dettagli della Casa -->
<div class="row align-items-center mb-4">
<div class="col-sm-8">
<h4 class="page-title m-0">Documenti per la Casa: <?php echo htmlspecialchars($homeData['name']); ?></h4>
<p class="mb-0"><strong>Indirizzo:</strong> <?php echo htmlspecialchars($homeData['address']) . ', ' . htmlspecialchars($homeData['city']) . ' ' . htmlspecialchars($homeData['zip']); ?></p>
</div>
</div>
<div class="row mb-4">
<div class="col-12 col-md-6 text-center text-md-start">
<label for="pageSelectDropdown" class="fw-bold d-block mb-2">Seleziona Categoria:</label>
<select id="pageSelectDropdown" class="form-control w-100 w-md-auto">
<?php foreach ($pages as $page) { ?>
<option value="<?php echo htmlspecialchars($page['slug']); ?>"
<?php echo ($docpage === $page['slug']) ? 'selected' : ''; ?>>
<?php echo ucfirst(htmlspecialchars($page['namepages'])); ?>
</option>
<?php } ?>
</select>
</div>
<div class="col-12 col-md-6 text-center text-md-end mt-3 mt-md-0">
<div class="input-group w-100 w-md-75 mx-auto mx-md-0">
<input type="text" id="documentSearch" class="form-control" placeholder="Cerca sezione o documento..." autocomplete="off">
<div id="searchResults" class="list-group dropdown-menu show" style="position: absolute; width: 100%; max-height: 200px; overflow-y: auto; z-index: 1000; display: none;"></div>
</div>
</div>
</div>
<!-- Contenitore per i documenti dinamici -->
<div id="documentSections" class="accordion"></div>
</div>
</div>
</div>
<style>
/* Personalizza la riga della sezione */
.section-header {
background-color: #f8f9fa;
border: 1px solid #007bff;
color: #007bff;
font-size: 1.2rem;
font-weight: bold;
padding: 15px 20px;
text-align: left;
width: 100%;
}
.section-header:hover {
background-color: #007bff;
color: #fff;
}
.accordion-button {
border-radius: 0 !important;
box-shadow: none !important;
}
.section-header i {
font-size: 1.5rem;
margin-right: 10px;
}
.section-title {
font-size: 1.25rem;
font-weight: bold;
color: #333;
margin-bottom: 20px;
}
.document-title {
font-size: 1.1rem;
font-weight: 500;
margin-bottom: 10px;
}
.dropzone {
background-color: #f0f8ff;
border: 2px dashed #007bff;
padding: 20px;
border-radius: 10px;
text-align: center;
transition: background-color 0.3s ease;
}
.dropzone:hover {
background-color: #e6f5ff;
}
.dropzone .dz-message {
font-size: 1.1rem;
font-weight: 500;
color: #007bff;
}
.dropzone .dz-message i {
font-size: 3rem;
margin-bottom: 10px;
color: #007bff;
}
.document-list-table th,
.document-list-table td {
text-align: center;
vertical-align: middle;
}
.section-separator {
border-top: 2px solid #ddd;
margin: 40px 0;
}
.btn {
margin-right: 5px;
}
.btn.active {
background-color: #007bff;
color: #fff;
}
.accordion-button {
background-color: #322999;
color: white;
font-size: 1.2rem;
font-weight: bold;
text-align: left;
border: 1px solid #007bff;
}
.accordion-button:hover {
background-color: #007bff;
color: white;
}
.accordion-button i {
font-size: 1.5rem;
color: #fff562;
}
.accordion-body {
padding: 20px;
background-color: #f9f9f9;
border: 1px solid #ddd;
}
.card-body {
margin-bottom: 20px;
padding: 15px;
background-color: #ffffff;
border: 1px solid #ddd;
border-radius: 5px;
}
.toggle-dropzone {
transition: all 0.3s ease;
font-size: 0.9rem;
}
.dropzone-container {
padding: 10px;
background-color: #f9f9f9;
border: 1px dashed #007bff;
border-radius: 8px;
display: none;
}
.input-group {
max-width: 400px;
margin: 0 auto;
}
#documentSearch {
border-radius: 0.25rem 0 0 0.25rem;
}
#searchResults {
background-color: #fff;
border: 1px solid #ddd;
border-radius: 0.25rem;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}
#searchResults .list-group-item {
cursor: pointer;
}
#searchResults .list-group-item:hover {
background-color: #f8f9fa;
}
@media (max-width: 767.98px) {
.input-group {
max-width: 100%;
margin-top: 10px;
}
#pageSelectDropdown,
#documentSearch {
width: 100% !important;
}
}
</style>
<script>
$(document).ready(function() {
// Inizializza Select2
$("#pageSelectDropdown").select2({
placeholder: "Seleziona una categoria...",
allowClear: true,
theme: "classic",
width: 'resolve'
});
// Caricamento iniziale dei documenti per lo slug predefinito
let idhome = <?php echo $idhome; ?>;
loadDocuments('<?php echo $docpage; ?>');
// Gestione del cambio del dropdown senza ricaricare la pagina
$("#pageSelectDropdown").on("change", function() {
const slug = $(this).val();
loadDocuments(slug);
});
// Carica tutti i documenti e le sezioni da tutte le pagine per la ricerca
let allDocuments = [];
<?php
$stmt = $pdo->query("
SELECT d.document_id, d.document_name, p.slug, s.section_name
FROM documents d
LEFT JOIN sections s ON d.idsections = s.idsections
LEFT JOIN pages p ON d.page_id = p.idpages
ORDER BY s.section_name, d.document_name
");
while ($doc = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo "allDocuments.push({
id: '{$doc['document_id']}',
name: '" . addslashes(htmlspecialchars($doc['document_name'])) . "',
section: '" . addslashes(htmlspecialchars($doc['section_name'])) . "',
slug: '" . addslashes(htmlspecialchars($doc['slug'])) . "'
});\n";
}
?>
// Gestione della ricerca dinamica
$('#documentSearch').on('input', function() {
const searchTerm = $(this).val().toLowerCase().trim();
$('#searchResults').empty().hide();
if (searchTerm === '') {
return;
}
const results = allDocuments.filter(item =>
item.name.toLowerCase().includes(searchTerm) ||
item.section.toLowerCase().includes(searchTerm)
);
if (results.length > 0) {
let html = '';
results.forEach(result => {
html += `<a href="#" class="list-group-item list-group-item-action" data-slug="${result.slug}" data-section="${md5(result.section)}">
${result.name} (Sezione: ${result.section})
</a>`;
});
$('#searchResults').html(html).show();
// Gestione del click sui risultati
$('#searchResults .list-group-item').on('click', function(e) {
e.preventDefault();
const slug = $(this).data('slug');
const sectionId = $(this).data('section');
// Aggiorna il dropdown e carica i documenti
$('#pageSelectDropdown').val(slug).trigger('change');
loadDocuments(slug, sectionId);
// Resetta il campo di ricerca e nasconde i risultati
$('#documentSearch').val('');
$('#searchResults').hide();
});
}
});
// Chiudi i risultati della ricerca se clicchi fuori
$(document).on('click', function(e) {
if (!$(e.target).closest('.input-group, #searchResults').length) {
$('#searchResults').hide();
}
});
function loadDocuments(slug, targetSectionId = null) {
$.ajax({
url: 'get-documents.php',
method: 'GET',
data: {
slug: slug,
idhome: idhome
},
dataType: 'json',
success: function(response) {
if (response.error) {
Swal.fire({
icon: 'error',
title: 'Errore',
text: response.error
});
return;
}
const homeName = response.homeName || 'Nome non disponibile';
const homeAddress = response.homeAddress || 'Indirizzo non disponibile';
const documents = response.documents || {};
const loadedDocuments = response.loadedDocuments || {};
// Aggiorna i dettagli della casa
$('.page-title').text(`Documenti per la Casa: ${homeName}`);
$('p.mb-0 strong').text(`Indirizzo: ${homeAddress}`);
// Svuota e ricrea le sezioni dei documenti
$('#documentSections').empty();
let html = '';
let sectionCount = 0;
for (let sectionName in documents) {
if (sectionCount >= 100) {
console.error('Troppi loop nelle sezioni, possibile errore nei dati');
break;
}
sectionCount++;
html += `
<div class="accordion-item">
<h2 class="accordion-header" id="heading-${md5(sectionName)}">
<button class="accordion-button collapsed section-header full-width" type="button" data-toggle="collapse" data-target="#collapse-${md5(sectionName)}" aria-expanded="false" aria-controls="collapse-${md5(sectionName)}">
<i class="fas fa-door-open"></i> ${sectionName}
</button>
</h2>
<div id="collapse-${md5(sectionName)}" class="accordion-collapse collapse" aria-labelledby="heading-${md5(sectionName)}" data-parent="#documentSections">
<div class="accordion-body">
`;
let docCount = 0;
(documents[sectionName] || []).forEach(document => {
if (docCount >= 100) {
console.error('Troppi loop nei documenti, possibile errore nei dati');
return;
}
docCount++;
html += `
<div class="card card-body mb-4">
<div class="document-header d-flex justify-content-between align-items-center p-3 mb-3" style="background-color: #e8f5e9; border-radius: 8px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);">
<div>
<span class="document-title fw-bold">${document.document_name || 'Documento senza nome'}</span>
${document.is_required ? '<span class="badge bg-danger ms-2" style="font-size: 1rem; padding: 0.5em 0.8em;">Obbligatorio</span>' : ''}
${document.max_documents > 0 ? `<span class="badge bg-info ms-2" style="font-size: 1rem; padding: 0.5em 0.8em;">Max: ${document.max_documents}</span>` : ''}
</div>
<button class="btn btn-sm btn-outline-primary toggle-dropzone" data-target="#dropzone-${document.document_id}">
<i class="fas fa-plus"></i>
</button>
</div>
<div class="dropzone-container collapse" id="dropzone-${document.document_id}">
<div class="dropzone mb-3" id="dropzone-area-${document.document_id}">
<div class="dz-message">
<i class="fas fa-cloud-upload-alt"></i><br>
Trascina qui i documenti o clicca per caricarli
</div>
</div>
<div class="text-center mt-3">
<label class="btn btn-outline-primary btn-sm">
<i class="fas fa-camera"></i> Scatta una foto
<input type="file" accept="image/*" capture="camera" id="cameraInput-${document.document_id}" class="d-none" onchange="uploadFromCamera(this, '${document.document_id}')">
</label>
</div>
</div>
<h6 class="mt-4">Documenti già caricati:</h6>
${(loadedDocuments[document.document_id] || []).length > 0 ? `
<table class="table table-bordered document-list-table" id="table-${document.document_id}">
<thead>
<tr>
<th>Nome Documento</th>
<th>Data Caricamento</th>
<th>Azioni</th>
</tr>
</thead>
<tbody>
${loadedDocuments[document.document_id].map(doc => `
<tr>
<td><a href="homedocuments/${doc.filename}" target="_blank">${doc.filename}</a></td>
<td>${doc.created_at}</td>
<td><button class="btn btn-danger btn-sm delete-document" data-id="${doc.id}" data-file="${doc.filename}">Elimina</button></td>
</tr>
`).join('')}
</tbody>
</table>
` : '<p class="text-muted">Nessun documento caricato</p>'}
</div>
`;
});
html += `
</div>
</div>
</div>
`;
}
$('#documentSections').html(html);
// Se c'è un targetSectionId, espandi solo quella sezione
if (targetSectionId) {
setTimeout(() => {
const collapseElement = $(`#collapse-${targetSectionId}`);
if (collapseElement.length) {
$('.accordion-collapse.collapse').collapse('hide');
collapseElement.collapse('show');
$('html, body').animate({
scrollTop: collapseElement.offset().top - 100
}, 500);
} else {
Swal.fire({
icon: 'warning',
title: 'Attenzione',
text: 'La sezione cercata non è stata trovata.'
});
}
}, 1000);
}
// Rinizializza Dropzone per ogni documento
for (let sectionName in documents) {
(documents[sectionName] || []).forEach(document => {
if (!Dropzone.instances.some(dz => dz.element.id === `dropzone-area-${document.document_id}`)) {
new Dropzone(`#dropzone-area-${document.document_id}`, {
url: "upload-document.php",
paramName: "file",
maxFiles: document.max_documents || 1,
maxFilesize: 5,
addRemoveLinks: true,
acceptedFiles: "image/*,application/pdf",
dictDefaultMessage: "Trascina qui i file o clicca per caricarli",
dictRemoveFile: "Rimuovi",
previewTemplate: `
<div class="dz-preview dz-file-preview">
<div class="dz-image"><img data-dz-thumbnail /></div>
<div class="dz-details">
<div class="dz-filename"><span data-dz-name></span></div>
<div class="dz-size"><span data-dz-size></span></div>
</div>
<div class="dz-progress">
<span class="dz-upload" data-dz-uploadprogress></span>
</div>
<div class="dz-error-message"><span data-dz-errormessage></span></div>
<div class="dz-success-mark">
<i class="fas fa-check-circle"></i>
</div>
<div class="dz-error-mark">
<i class="fas fa-times-circle"></i>
</div>
</div>
`,
init: function() {
this.on("success", function(file, response) {
try {
let parsedResponse = typeof response === "string" ? JSON.parse(response) : response;
if (parsedResponse.success) {
let tableId = `#table-${document.document_id} tbody`;
let row = `
<tr>
<td><a href="homedocuments/${parsedResponse.fileName}" target="_blank">${parsedResponse.fileName}</a></td>
<td>${parsedResponse.uploadDate}</td>
<td><button class="btn btn-danger btn-sm delete-document" data-id="${parsedResponse.documentId}" data-file="${parsedResponse.fileName}">Elimina</button></td>
</tr>`;
$(tableId).append(row);
} else {
Swal.fire({
icon: "error",
title: "Errore",
text: parsedResponse.message || "Errore nel caricamento",
});
}
} catch (error) {
console.error("Errore nel parsing della risposta:", error);
Swal.fire({
icon: "error",
title: "Errore",
text: "Risposta dal server non valida.",
});
}
});
this.on("error", function(file, errorMessage) {
Swal.fire({
icon: "error",
title: "Errore",
text: errorMessage || "Si è verificato un problema.",
});
this.removeFile(file);
});
},
sending: function(file, xhr, formData) {
formData.append("idhome", idhome);
formData.append("document_id", document.document_id);
}
});
}
});
}
// Rinizializza il toggle Dropzone
document.querySelectorAll('.toggle-dropzone').forEach(button => {
button.addEventListener('click', function() {
const target = document.querySelector(this.dataset.target);
const icon = this.querySelector('i');
if (target.classList.contains('show')) {
target.classList.remove('show');
target.style.display = 'none';
icon.classList.remove('fa-minus');
icon.classList.add('fa-plus');
} else {
target.classList.add('show');
target.style.display = 'block';
icon.classList.remove('fa-plus');
icon.classList.add('fa-minus');
}
});
});
// Rinizializza la gestione dei documenti eliminati
$(document).on("click", ".delete-document", function() {
const documentId = $(this).data("id");
const fileName = $(this).data("file");
const $row = $(this).closest("tr");
Swal.fire({
title: "Sei sicuro?",
text: "Questa azione eliminerà il documento in modo permanente.",
icon: "warning",
showCancelButton: true,
confirmButtonColor: "#d33",
cancelButtonColor: "#3085d6",
confirmButtonText: "Sì, elimina",
cancelButtonText: "Annulla",
}).then((result) => {
if (result.isConfirmed) {
$.ajax({
url: "delete-document.php",
type: "POST",
data: {
document_id: documentId,
file_name: fileName,
},
success: function(response) {
try {
const parsedResponse = typeof response === "string" ? JSON.parse(response) : response;
if (parsedResponse.success) {
$row.remove();
Swal.fire({
icon: "success",
title: "Eliminato",
text: "Documento eliminato con successo.",
timer: 1500,
showConfirmButton: false,
});
} else {
Swal.fire({
icon: "error",
title: "Errore",
text: parsedResponse.message || "Impossibile eliminare il documento.",
});
}
} catch (error) {
console.error("Errore durante l'eliminazione:", error);
Swal.fire({
icon: "error",
title: "Errore",
text: "Risposta dal server non valida.",
});
}
},
error: function() {
Swal.fire({
icon: "error",
title: "Errore",
text: "Si è verificato un problema con la richiesta.",
});
},
});
}
});
});
// Funzione per caricare un file dalla fotocamera
window.uploadFromCamera = function(input, documentId) {
if (input.files && input.files[0]) {
let formData = new FormData();
formData.append("file", input.files[0]);
formData.append("idhome", idhome);
formData.append("document_id", documentId);
$.ajax({
url: "upload-document.php",
type: "POST",
data: formData,
processData: false,
contentType: false,
success: function(response) {
try {
let parsedResponse = typeof response === "string" ? JSON.parse(response) : response;
if (parsedResponse.success) {
let tableId = `#table-${documentId} tbody`;
let row = `
<tr>
<td><a href="homedocuments/${parsedResponse.fileName}" target="_blank">${parsedResponse.fileName}</a></td>
<td>${parsedResponse.uploadDate}</td>
<td><button class="btn btn-danger btn-sm delete-document" data-id="${parsedResponse.documentId}" data-file="${parsedResponse.fileName}">Elimina</button></td>
</tr>`;
$(tableId).append(row);
Swal.fire({
icon: "success",
title: "Caricamento completato",
text: "La foto è stata caricata con successo.",
timer: 1500,
showConfirmButton: false
});
} else {
Swal.fire({
icon: "error",
title: "Errore",
text: parsedResponse.message || "Errore nel caricamento",
});
}
} catch (error) {
console.error("Errore nel parsing della risposta:", error);
Swal.fire({
icon: "error",
title: "Errore",
text: "Risposta dal server non valida.",
});
}
},
error: function() {
Swal.fire({
icon: "error",
title: "Errore",
text: "Si è verificato un problema con il caricamento.",
});
}
});
}
};
},
error: function(xhr, status, error) {
Swal.fire({
icon: 'error',
title: 'Errore',
text: 'Impossibile caricare i documenti: ' + error
});
}
});
}
});
</script>

View File

@ -0,0 +1,799 @@
<?php
global $idhome, $isNew, $homeData, $namedb, $addressdb, $countrydb, $citydb, $zipdb, $commentdb, $latitudedb, $longitudedb, $fulladdressdb;
require_once dirname(__DIR__) . '/class/db-functions.php';
$dbHandler = DBHandlerSelect::getInstance();
$pdo = $dbHandler->getConnection();
// Recupera i dettagli dell'immobile
$stmt = $pdo->prepare("SELECT name, address, zip, city, country FROM home WHERE idhome = ?");
$stmt->execute([$idhome]);
$homeDetails = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$homeDetails) {
die("Immobile non trovato o accesso non autorizzato.");
}
// Recupera i proprietari associati all'immobile
$stmt = $pdo->prepare("
SELECT
po.owner_id,
po.first_name,
po.last_name,
po.company_name,
po.tax_code,
po.email,
ho.ownership_percentage,
ho.notes
FROM
home_owners AS ho
INNER JOIN
property_owners AS po ON ho.owner_id = po.owner_id
WHERE
ho.home_id = ?
");
$stmt->execute([$idhome]);
$owners = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Recupera tutti i proprietari disponibili dell'utente per la selezione
$stmt = $pdo->prepare("
SELECT
owner_id,
first_name,
last_name,
company_name,
tax_code
FROM
property_owners
WHERE
user_id = ?
AND owner_id NOT IN (
SELECT owner_id FROM home_owners WHERE home_id = ?
)
");
$stmt->execute([$iduserlogin, $idhome]);
$availableOwners = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<style>
/* Stile per l'overlay dello spinner */
.loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 9999;
display: none;
}
.loading-overlay .spinner-custom {
width: 4rem;
height: 4rem;
border: 4px solid #fff;
border-top: 4px solid #007bff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
.loading-overlay .spinner-text {
color: #fff;
font-size: 1.2rem;
margin-top: 1rem;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
<div class="card card-body">
<!-- Overlay dello spinner -->
<div id="loading-overlay" class="loading-overlay">
<div class="spinner-custom"></div>
<div class="spinner-text">Caricamento...</div>
</div>
<!-- Dettagli dell'immobile -->
<div class="card-header bg-warning text-white mb-4">
<h4 class="mb-0"><?php echo htmlspecialchars($homeDetails['name']); ?></h4>
<span class="badge bg-info text-primary">
<?php echo htmlspecialchars($homeDetails['address'] . ', ' . $homeDetails['zip'] . ', ' . $homeDetails['city'] . ', ' . $homeDetails['country']); ?>
</span>
</div>
<!-- Proprietari associati -->
<div class="card mb-4">
<div class="card-header bg-success text-white">
<h5 class="mb-0">Proprietari</h5>
</div>
<div class="card-body">
<?php if (!empty($owners)) { ?>
<div id="ownersTable">
<table class="table table-bordered">
<thead>
<tr>
<th>Nome</th>
<th>Codice Fiscale</th>
<th>%</th>
<th>Note</th>
<th>Azioni</th>
</tr>
</thead>
<tbody id="ownersTableBody">
<?php
$totalPercentage = 0;
foreach ($owners as $owner) {
$totalPercentage += $owner['ownership_percentage'];
echo "<tr>
<td>" . htmlspecialchars($owner['first_name'] . ' ' . $owner['last_name']) . "</td>
<td>" . htmlspecialchars($owner['tax_code']) . "</td>
<td class='ownership-percentage'>" . htmlspecialchars($owner['ownership_percentage']) . "</td>
<td>" . htmlspecialchars($owner['notes']) . "</td>
<td>
<button class='btn btn-danger btn-sm remove-owner-btn' data-id='" . $owner['owner_id'] . "'>
<i class='fas fa-trash-alt'></i> Rimuovi
</button>
</td>
</tr>";
}
?>
</tbody>
<tfoot>
<tr>
<td colspan="2"><strong>Totale % Proprietà:</strong></td>
<td id="totalOwnership" class="font-weight-bold text-center"><?php echo $totalPercentage; ?>%</td>
<td colspan="2"></td>
</tr>
</tfoot>
</table>
</div>
<?php } else { ?>
<div id="ownersTable">
<p class="text-muted">Nessun proprietario associato.</p>
</div>
<?php } ?>
</div>
</div>
<!-- Aggiungi proprietari -->
<div class="card mb-4">
<div class="card-header bg-info text-white">
<h5 class="mb-0">Assegna Proprietari</h5>
</div>
<div class="card-body">
<form id="addOwnerForm" method="POST">
<input type="hidden" name="idhome" value="<?php echo $idhome; ?>">
<div class="form-group">
<label for="ownerSelect">Seleziona Proprietario</label>
<select class="form-control" id="ownerSelect" name="owner_id" required>
<option value="">-- Seleziona --</option>
<?php foreach ($availableOwners as $availableOwner) { ?>
<option value="<?php echo $availableOwner['owner_id']; ?>">
<?php
echo htmlspecialchars($availableOwner['first_name'] . ' ' . $availableOwner['last_name']);
if ($availableOwner['company_name']) {
echo ' (' . htmlspecialchars($availableOwner['company_name']) . ')';
}
echo ' - ' . htmlspecialchars($availableOwner['tax_code']);
?>
</option>
<?php } ?>
<option value="new_owner"> Aggiungi nuovo proprietario</option>
</select>
</div>
<div class="form-group">
<label for="ownershipPercentage">Percentuale di Proprietà</label>
<input type="number" step="0.01" class="form-control" id="ownershipPercentage" name="ownership_percentage" placeholder="Inserisci la percentuale (es. 50.00)" required>
</div>
<div class="form-group">
<label for="notes">Note</label>
<textarea class="form-control" id="notes" name="notes" rows="3" placeholder="Aggiungi eventuali note"></textarea>
</div>
<!-- Messaggio di errore -->
<small id="percentageError" class="text-danger" style="display:none;">La somma totale non può superare il 100%.</small>
<button type="submit" id="addOwnerBtn" class="btn btn-success mt-3">Aggiungi</button>
</form>
</div>
</div>
</div>
<!-- Modal Aggiungi Nuovo Proprietario -->
<div class="modal fade" id="newOwnerModal" tabindex="-1" aria-labelledby="newOwnerModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="newOwnerModalLabel">Aggiungi Nuovo Proprietario</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form id="newOwnerForm">
<input type="hidden" name="user_id" value="<?php echo $iduserlogin; ?>">
<div class="row">
<!-- Tipo Proprietario -->
<div class="col-md-6">
<div class="form-group">
<label for="ownerType">Tipo Proprietario</label>
<select class="form-control" id="ownerType" name="owner_type" required>
<option value="individual">Persona Fisica</option>
<option value="company">Azienda</option>
</select>
</div>
</div>
<!-- Codice Fiscale / P. IVA -->
<div class="col-md-6">
<div class="form-group">
<label for="taxCode">Codice Fiscale / Partita IVA</label>
<input type="text" class="form-control" id="taxCode" name="tax_code" required>
</div>
</div>
<!-- Nome -->
<div class="col-md-6">
<div class="form-group">
<label for="firstName">Nome</label>
<input type="text" class="form-control" id="firstName" name="first_name">
</div>
</div>
<!-- Cognome -->
<div class="col-md-6">
<div class="form-group">
<label for="lastName">Cognome</label>
<input type="text" class="form-control" id="lastName" name="last_name">
</div>
</div>
<!-- Nome Azienda -->
<div class="col-md-12">
<div class="form-group">
<label for="companyName">Nome Azienda</label>
<input type="text" class="form-control" id="companyName" name="company_name" disabled>
</div>
</div>
<!-- Email -->
<div class="col-md-6">
<div class="form-group">
<label for="email">Email</label>
<input type="email" class="form-control" id="email" name="email" required>
</div>
</div>
<!-- Telefono -->
<div class="col-md-6">
<div class="form-group">
<label for="phone">Telefono</label>
<input type="text" class="form-control" id="phone" name="phone">
</div>
</div>
<!-- Indirizzo -->
<div class="col-md-6">
<div class="form-group">
<label for="address">Indirizzo</label>
<input type="text" class="form-control" id="address" name="address">
</div>
</div>
<!-- CAP -->
<div class="col-md-3">
<div class="form-group">
<label for="postalCode">CAP</label>
<input type="text" class="form-control" id="postalCode" name="postal_code">
</div>
</div>
<!-- Città -->
<div class="col-md-3">
<div class="form-group">
<label for="city">Città</label>
<input type="text" class="form-control" id="city" name="city">
</div>
</div>
<!-- Provincia -->
<div class="col-md-6">
<div class="form-group">
<label for="province">Provincia</label>
<input type="text" class="form-control" id="province" name="province">
</div>
</div>
<!-- Nazione -->
<div class="col-md-6">
<div class="form-group">
<label for="country">Nazione</label>
<select class="form-control" id="country" name="country">
<option value="">-- Seleziona --</option>
<?php
$stmt = $pdo->query("SELECT id, name FROM auth_countries ORDER BY name");
while ($country = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo "<option value='{$country['id']}'>" . htmlspecialchars($country['name']) . "</option>";
}
?>
</select>
</div>
</div>
<!-- Ruolo -->
<div class="col-md-6">
<div class="form-group">
<label for="role">Ruolo</label>
<input type="text" class="form-control" id="role" name="role">
</div>
</div>
<!-- Note -->
<div class="col-md-12">
<div class="form-group">
<label for="notes">Note</label>
<textarea class="form-control" id="notes" name="notes" rows="3"></textarea>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Annulla</button>
<button type="submit" class="btn btn-success">Salva Proprietario</button>
</div>
</form>
</div>
</div>
</div>
</div>
<script>
// Passa iduserlogin come variabile JavaScript
const iduserlogin = <?php echo $iduserlogin; ?>;
$(document).ready(function() {
// Verifica che jQuery sia caricato
if (typeof jQuery === "undefined") {
console.error("jQuery non è caricato!");
Swal.fire({
icon: "error",
title: "Errore",
text: "jQuery non è caricato. Contatta l'amministratore."
});
return;
}
// Verifica che Bootstrap modal sia caricato
if (typeof $.fn.modal === "undefined") {
console.error("Bootstrap modal non è caricato!");
Swal.fire({
icon: "error",
title: "Errore",
text: "Bootstrap modal non è caricato. Contatta l'amministratore."
});
return;
}
// Inizializza Select2 se disponibile, altrimenti usa il dropdown nativo
let isSelect2Available = typeof $.fn.select2 !== "undefined";
if (isSelect2Available) {
$("#country").select2({
width: '100%',
placeholder: "Seleziona un paese...",
allowClear: true
});
$("#ownerSelect").select2({
width: '100%',
placeholder: "-- Seleziona --"
});
} else {
console.warn("Select2 non è disponibile, utilizzo dropdown nativo.");
}
// Gestione del totale percentuale e colore
function updateTotalOwnership() {
let total = 0;
document.querySelectorAll(".ownership-percentage").forEach(function(el) {
total += parseFloat(el.textContent) || 0;
});
const totalCell = document.getElementById("totalOwnership");
// Controlla se totalCell esiste prima di aggiornarlo
if (!totalCell) {
console.warn("Elemento #totalOwnership non trovato nel DOM. Probabilmente non ci sono proprietari associati.");
return total;
}
totalCell.textContent = total.toFixed(2) + "%";
if (total >= 100) {
totalCell.style.backgroundColor = "#28a745"; // Verde
totalCell.style.color = "#fff";
document.getElementById("addOwnerForm").style.display = "none"; // Nasconde il form se il totale è 100%
} else {
totalCell.style.backgroundColor = "#ffc107"; // Arancione
totalCell.style.color = "#212529";
document.getElementById("addOwnerForm").style.display = "block";
}
return total;
}
// Validazione percentuale in tempo reale
$("#ownershipPercentage").on("input", function() {
let totalOwnership = updateTotalOwnership();
let newPercentage = parseFloat(this.value) || 0;
let remainingPercentage = 100 - totalOwnership;
let errorMsg = document.getElementById("percentageError");
let submitBtn = document.getElementById("addOwnerBtn");
if (newPercentage > remainingPercentage) {
errorMsg.style.display = "block";
submitBtn.disabled = true;
} else {
errorMsg.style.display = "none";
submitBtn.disabled = false;
}
});
// Inizializza il totale all'avvio
updateTotalOwnership();
// Selezione del proprietario nel dropdown
$("#ownerSelect").on("change", function() {
console.log("ownerSelect cambiato, valore:", $(this).val());
if ($(this).val() === "new_owner") {
try {
$("#newOwnerModal").modal("show");
$(this).val("").trigger("change");
} catch (e) {
console.error("Errore apertura modale:", e);
Swal.fire({
icon: "error",
title: "Errore",
text: "Impossibile aprire il modale per aggiungere un nuovo proprietario: " + e.message
});
}
}
});
// Abilita/disabilita i campi in base al tipo di proprietario
$("#ownerType").on("change", function() {
if ($(this).val() === "company") {
$("#companyName").prop("disabled", false);
$("#firstName, #lastName").prop("disabled", true).val("");
} else {
$("#companyName").prop("disabled", true).val("");
$("#firstName, #lastName").prop("disabled", false);
}
});
// Funzione per aggiornare il dropdown
function updateOwnerSelect() {
return fetch(`get-available-owners.php?idhome=<?php echo $idhome; ?>&iduser=${iduserlogin}`)
.then(response => {
if (!response.ok) {
throw new Error('Errore nella risposta del server: ' + response.statusText);
}
return response.text();
})
.then(html => {
const tempDiv = document.createElement("div");
tempDiv.innerHTML = html;
const newSelect = tempDiv.querySelector("select#ownerSelect");
if (newSelect) {
const ownerSelect = document.getElementById("ownerSelect");
ownerSelect.innerHTML = newSelect.innerHTML;
if (isSelect2Available) {
// Distruggi l'istanza precedente di Select2
$("#ownerSelect").select2('destroy');
// Inizializza Select2
$("#ownerSelect").select2({
width: "100%",
placeholder: "-- Seleziona --",
allowClear: true
});
// Forza Select2 a mostrare l'opzione vuota come selezionabile
const optionsCount = ownerSelect.options.length;
if (optionsCount <= 2) {
$("#ownerSelect").val(null).trigger('change');
}
}
// Debug: verifica quante opzioni ci sono nel dropdown
const optionsCount = ownerSelect.options.length;
console.log("Numero di opzioni nel dropdown dopo aggiornamento:", optionsCount);
// Verifica se il dropdown ha almeno l'opzione "Aggiungi nuovo"
const hasAddNewOption = Array.from(ownerSelect.options).some(option => option.value === "new_owner");
if (!hasAddNewOption) {
const newOption = new Option(" Aggiungi nuovo proprietario", "new_owner");
ownerSelect.appendChild(newOption);
if (isSelect2Available) {
$("#ownerSelect").trigger('change');
}
}
} else {
throw new Error("Elemento select#ownerSelect non trovato nel risultato.");
}
})
.catch(error => {
console.error("Errore aggiornamento dropdown:", error);
const ownerSelect = document.getElementById("ownerSelect");
ownerSelect.innerHTML = '<option value="">-- Seleziona --</option><option value="new_owner"> Aggiungi nuovo proprietario</option>';
if (isSelect2Available) {
$("#ownerSelect").select2({
width: "100%",
placeholder: "-- Seleziona --",
allowClear: true
});
}
Swal.fire({
icon: "error",
title: "Errore",
text: "Errore nell'aggiornamento del dropdown dei proprietari: " + error.message
});
});
}
// Funzione per aggiornare la tabella
function updateOwnersTable() {
return fetch("get-owners.php?idhome=<?php echo $idhome; ?>")
.then(response => {
if (!response.ok) {
throw new Error('Errore nella risposta del server: ' + response.statusText);
}
return response.text();
})
.then(html => {
document.getElementById("ownersTable").innerHTML = html;
updateTotalOwnership();
})
.catch(error => {
console.error("Errore aggiornamento tabella:", error);
Swal.fire({
icon: "error",
title: "Errore",
text: "Errore nell'aggiornamento della tabella dei proprietari: " + error.message
});
});
}
// Validazione client-side del form del nuovo proprietario
$("#newOwnerForm").on("submit", function(e) {
e.preventDefault();
const taxCode = $("#taxCode").val().trim();
const email = $("#email").val().trim();
const ownerType = $("#ownerType").val();
const firstName = $("#firstName").val().trim();
const lastName = $("#lastName").val().trim();
const companyName = $("#companyName").val().trim();
// Controlli di validazione
if (!taxCode) {
Swal.fire({
icon: "error",
title: "Errore",
text: "Il codice fiscale o partita IVA è obbligatorio."
});
return;
}
if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
Swal.fire({
icon: "error",
title: "Errore",
text: "Inserisci un'email valida."
});
return;
}
if (ownerType === "individual" && (!firstName || !lastName)) {
Swal.fire({
icon: "error",
title: "Errore",
text: "Nome e cognome sono obbligatori per una persona fisica."
});
return;
}
if (ownerType === "company" && !companyName) {
Swal.fire({
icon: "error",
title: "Errore",
text: "Il nome dell'azienda è obbligatorio per un'azienda."
});
return;
}
const loadingOverlay = document.getElementById("loading-overlay");
loadingOverlay.style.display = "flex";
$.post("add-new-owner.php", $(this).serialize(), function(response) {
loadingOverlay.style.display = "none";
let result;
try {
result = JSON.parse(response);
} catch (e) {
Swal.fire({
icon: "error",
title: "Errore",
text: "Risposta non valida dal server: " + e.message
});
return;
}
if (result.success) {
Swal.fire({
icon: "success",
title: "Proprietario aggiunto!",
text: result.message,
timer: 1500,
showConfirmButton: false
}).then(() => {
$("#newOwnerModal").modal("hide");
// Aggiorna la tabella dei proprietari
updateOwnersTable();
// Aggiorna il dropdown dei proprietari disponibili
updateOwnerSelect();
// Resetta il form del modale
$("#newOwnerForm")[0].reset();
$("#companyName").prop("disabled", true);
$("#firstName, #lastName").prop("disabled", false);
});
} else {
Swal.fire({
icon: "error",
title: "Errore",
text: result.message
});
}
}).fail(function(jqXHR, textStatus, errorThrown) {
loadingOverlay.style.display = "none";
Swal.fire({
icon: "error",
title: "Errore",
text: "Si è verificato un problema con la richiesta: " + textStatus + " - " + errorThrown
});
});
});
// Aggiunta di un proprietario esistente
$("#addOwnerForm").on("submit", function(e) {
e.preventDefault();
const ownerId = $("#ownerSelect").val();
const percentage = parseFloat($("#ownershipPercentage").val()) || 0;
const totalOwnership = updateTotalOwnership();
if (!ownerId) {
Swal.fire({
icon: "error",
title: "Errore",
text: "Seleziona un proprietario."
});
return;
}
if (totalOwnership + percentage > 100) {
Swal.fire({
icon: "error",
title: "Errore",
text: "La somma totale dei proprietari supererebbe il 100%."
});
return;
}
const loadingOverlay = document.getElementById("loading-overlay");
loadingOverlay.style.display = "flex";
let formData = new FormData(this);
fetch("add-owner-to-home.php", {
method: "POST",
body: formData,
})
.then(response => response.json())
.then(data => {
loadingOverlay.style.display = "none";
if (data.success) {
Swal.fire({
icon: "success",
title: "Proprietario aggiunto!",
text: data.message,
timer: 1500,
showConfirmButton: false
}).then(() => {
// Aggiorna la tabella dei proprietari
updateOwnersTable();
// Aggiorna il dropdown dei proprietari disponibili
updateOwnerSelect();
// Resetta il form
this.reset();
$("#ownerSelect").val("").trigger("change");
});
} else {
Swal.fire({
icon: "error",
title: "Errore",
text: data.message
});
}
})
.catch(error => {
loadingOverlay.style.display = "none";
Swal.fire({
icon: "error",
title: "Errore",
text: "Si è verificato un problema con la richiesta: " + error.message
});
});
});
// Rimozione di un proprietario
$(document).on("click", ".remove-owner-btn", function() {
const ownerId = $(this).data("id");
const idhome = "<?php echo $idhome; ?>";
Swal.fire({
title: "Sei sicuro?",
text: "Questa azione rimuoverà il proprietario selezionato.",
icon: "warning",
showCancelButton: true,
confirmButtonColor: "#d33",
cancelButtonColor: "#3085d6",
confirmButtonText: "Sì, rimuovi",
cancelButtonText: "Annulla",
}).then((result) => {
if (result.isConfirmed) {
const loadingOverlay = document.getElementById("loading-overlay");
loadingOverlay.style.display = "flex";
$.post("remove-owner-from-home.php", {
owner_id: ownerId,
idhome: idhome
}, function(response) {
loadingOverlay.style.display = "none";
let result;
try {
result = JSON.parse(response);
} catch (e) {
Swal.fire({
icon: "error",
title: "Errore",
text: "Risposta non valida dal server: " + e.message
});
return;
}
if (result.success) {
Swal.fire({
icon: "success",
title: "Rimosso",
text: result.message,
timer: 1500,
showConfirmButton: false,
}).then(() => {
// Aggiorna la tabella dei proprietari
updateOwnersTable();
// Aggiorna il dropdown dei proprietari disponibili
updateOwnerSelect();
});
} else {
Swal.fire({
icon: "error",
title: "Errore",
text: result.message,
});
}
}).fail(function(jqXHR, textStatus, errorThrown) {
loadingOverlay.style.display = "none";
Swal.fire({
icon: "error",
title: "Errore",
text: "Impossibile completare la richiesta: " + textStatus + " - " + errorThrown
});
});
}
});
});
});
</script>