Initial commit
This commit is contained in:
@@ -0,0 +1,557 @@
|
||||
<?php
|
||||
// admin_subscription_plans.php
|
||||
|
||||
// Show errors (remove in production)
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
include('include/headscript.php');
|
||||
|
||||
// DB connection
|
||||
$dbHandler = DBHandlerSelect::getInstance();
|
||||
$pdo = $dbHandler->getConnection();
|
||||
|
||||
// Check login
|
||||
if (!isset($iduserlogin)) {
|
||||
die("Errore: ID utente non definito.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current user is admin.
|
||||
* IMPORTANT: set your real admin role_id(s) here.
|
||||
*/
|
||||
function isAdmin(PDO $pdo, int $userId): bool
|
||||
{
|
||||
// TODO: adjust these role ids according to your system
|
||||
$adminRoleIds = [1]; // e.g. 1 = superadmin
|
||||
|
||||
$stmt = $pdo->prepare("SELECT role_id FROM auth_users WHERE id = ?");
|
||||
$stmt->execute([$userId]);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$row) return false;
|
||||
return in_array((int)$row['role_id'], $adminRoleIds, true);
|
||||
}
|
||||
|
||||
if (!isAdmin($pdo, (int)$iduserlogin)) {
|
||||
die("Accesso negato: pagina riservata all'amministratore.");
|
||||
}
|
||||
|
||||
function formatMoneyFromCents(int $cents, string $currency): string
|
||||
{
|
||||
$amount = number_format($cents / 100, 2, ',', '.');
|
||||
return $amount . ' ' . strtoupper($currency);
|
||||
}
|
||||
|
||||
// Handle POST actions
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$action = $_POST['action'] ?? '';
|
||||
|
||||
// Common fields
|
||||
$code = trim($_POST['code'] ?? '');
|
||||
$name = trim($_POST['name'] ?? '');
|
||||
$description = trim($_POST['description'] ?? '');
|
||||
|
||||
$stripe_product_id = trim($_POST['stripe_product_id'] ?? '');
|
||||
$stripe_price_id = trim($_POST['stripe_price_id'] ?? '');
|
||||
|
||||
$currency = strtoupper(trim($_POST['currency'] ?? 'EUR'));
|
||||
$unit_amount = (int)($_POST['unit_amount'] ?? 0); // cents
|
||||
$interval = in_array(($_POST['interval'] ?? ''), ['day', 'week', 'month', 'year'], true) ? $_POST['interval'] : 'month';
|
||||
$interval_count = max(1, (int)($_POST['interval_count'] ?? 1));
|
||||
$trial_days = max(0, (int)($_POST['trial_days'] ?? 0));
|
||||
$is_active = isset($_POST['is_active']) ? 1 : 0;
|
||||
|
||||
// ADD
|
||||
if ($action === 'add_plan') {
|
||||
if ($code === '' || $name === '') {
|
||||
$error = "Code e Nome sono obbligatori.";
|
||||
} elseif ($stripe_price_id === '') {
|
||||
$error = "Stripe Price ID è obbligatorio (campo NOT NULL in tabella).";
|
||||
} elseif (strlen($currency) !== 3) {
|
||||
$error = "Currency deve essere nel formato ISO (es. EUR).";
|
||||
} elseif ($unit_amount < 0) {
|
||||
$error = "Unit amount non può essere negativo.";
|
||||
} else {
|
||||
try {
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO billing_plans
|
||||
(code, name, description, stripe_product_id, stripe_price_id, currency, unit_amount, `interval`, interval_count, trial_days, is_active, created_at, updated_at)
|
||||
VALUES
|
||||
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())
|
||||
");
|
||||
$stmt->execute([
|
||||
$code,
|
||||
$name,
|
||||
$description ?: null,
|
||||
$stripe_product_id ?: null,
|
||||
$stripe_price_id,
|
||||
$currency,
|
||||
$unit_amount,
|
||||
$interval,
|
||||
$interval_count,
|
||||
$trial_days,
|
||||
$is_active
|
||||
]);
|
||||
$success_message = "Piano creato con successo.";
|
||||
} catch (PDOException $e) {
|
||||
$error = "Errore durante la creazione del piano: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// EDIT
|
||||
if ($action === 'edit_plan') {
|
||||
$id = (int)($_POST['id'] ?? 0);
|
||||
|
||||
if ($id <= 0) {
|
||||
$error = "ID piano non valido.";
|
||||
} elseif ($code === '' || $name === '') {
|
||||
$error = "Code e Nome sono obbligatori.";
|
||||
} elseif ($stripe_price_id === '') {
|
||||
$error = "Stripe Price ID è obbligatorio (campo NOT NULL in tabella).";
|
||||
} elseif (strlen($currency) !== 3) {
|
||||
$error = "Currency deve essere nel formato ISO (es. EUR).";
|
||||
} elseif ($unit_amount < 0) {
|
||||
$error = "Unit amount non può essere negativo.";
|
||||
} else {
|
||||
try {
|
||||
$stmt = $pdo->prepare("
|
||||
UPDATE billing_plans
|
||||
SET
|
||||
code = ?,
|
||||
name = ?,
|
||||
description = ?,
|
||||
stripe_product_id = ?,
|
||||
stripe_price_id = ?,
|
||||
currency = ?,
|
||||
unit_amount = ?,
|
||||
`interval` = ?,
|
||||
interval_count = ?,
|
||||
trial_days = ?,
|
||||
is_active = ?,
|
||||
updated_at = NOW()
|
||||
WHERE id = ?
|
||||
");
|
||||
$stmt->execute([
|
||||
$code,
|
||||
$name,
|
||||
$description ?: null,
|
||||
$stripe_product_id ?: null,
|
||||
$stripe_price_id,
|
||||
$currency,
|
||||
$unit_amount,
|
||||
$interval,
|
||||
$interval_count,
|
||||
$trial_days,
|
||||
$is_active,
|
||||
$id
|
||||
]);
|
||||
$success_message = "Piano aggiornato con successo.";
|
||||
} catch (PDOException $e) {
|
||||
$error = "Errore durante l'aggiornamento del piano: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DISABLE
|
||||
if ($action === 'disable_plan') {
|
||||
$id = (int)($_POST['id'] ?? 0);
|
||||
if ($id <= 0) {
|
||||
$error = "ID piano non valido.";
|
||||
} else {
|
||||
$stmt = $pdo->prepare("UPDATE billing_plans SET is_active = 0, updated_at = NOW() WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$success_message = "Piano disattivato.";
|
||||
}
|
||||
}
|
||||
|
||||
// ENABLE
|
||||
if ($action === 'enable_plan') {
|
||||
$id = (int)($_POST['id'] ?? 0);
|
||||
if ($id <= 0) {
|
||||
$error = "ID piano non valido.";
|
||||
} else {
|
||||
$stmt = $pdo->prepare("UPDATE billing_plans SET is_active = 1, updated_at = NOW() WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$success_message = "Piano riattivato.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch plans
|
||||
$stmt = $pdo->prepare("SELECT * FROM billing_plans ORDER BY is_active DESC, name ASC");
|
||||
$stmt->execute();
|
||||
$plans = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
?>
|
||||
|
||||
<!doctype html>
|
||||
<html lang="it">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" href="assets/images/favicon-32x32.png" type="image/png" />
|
||||
<?php include('cssinclude.php'); ?>
|
||||
<?php include('siteinfo.php'); ?>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<?php include('include/navbar.php'); ?>
|
||||
<?php include('include/topbar.php'); ?>
|
||||
|
||||
<div class="page-wrapper">
|
||||
<div class="page-content">
|
||||
|
||||
<div class="card radius-10 mb-4">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<div>
|
||||
<h5 class="mb-1">Subscription Plans (Admin)</h5>
|
||||
<p class="mb-0 text-muted">Gestione piani abbonamento delle scuole</p>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addPlanModal">
|
||||
<i class="bx bx-plus"></i> Nuovo Piano
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (isset($error)): ?>
|
||||
<div class="alert alert-danger" role="alert"><?php echo htmlspecialchars($error); ?></div>
|
||||
<?php endif; ?>
|
||||
<?php if (isset($success_message)): ?>
|
||||
<div class="alert alert-success" role="alert"><?php echo htmlspecialchars($success_message); ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="card radius-10">
|
||||
<div class="card-header">
|
||||
<h6 class="mb-0">Elenco Piani</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table id="plansTable" class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Code</th>
|
||||
<th>Nome</th>
|
||||
<th>Prezzo</th>
|
||||
<th>Intervallo</th>
|
||||
<th>Trial</th>
|
||||
<th>Stripe Product</th>
|
||||
<th>Stripe Price *</th>
|
||||
<th>Stato</th>
|
||||
<th>Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($plans as $p): ?>
|
||||
<tr>
|
||||
<td><span class="badge bg-dark"><?php echo htmlspecialchars($p['code']); ?></span></td>
|
||||
<td>
|
||||
<div class="fw-bold"><?php echo htmlspecialchars($p['name']); ?></div>
|
||||
<?php if (!empty($p['description'])): ?>
|
||||
<div class="text-muted small"><?php echo nl2br(htmlspecialchars($p['description'])); ?></div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?php echo formatMoneyFromCents((int)$p['unit_amount'], $p['currency']); ?></td>
|
||||
<td><?php echo (int)$p['interval_count'] . ' / ' . htmlspecialchars($p['interval']); ?></td>
|
||||
<td><?php echo (int)$p['trial_days'] > 0 ? ((int)$p['trial_days'] . ' gg') : '—'; ?></td>
|
||||
<td>
|
||||
<?php if (!empty($p['stripe_product_id'])): ?>
|
||||
<span class="badge bg-secondary"><?php echo htmlspecialchars($p['stripe_product_id']); ?></span>
|
||||
<?php else: ?>
|
||||
<span class="text-muted">—</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-info"><?php echo htmlspecialchars($p['stripe_price_id']); ?></span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge <?php echo ((int)$p['is_active'] === 1) ? 'bg-success' : 'bg-danger'; ?>">
|
||||
<?php echo ((int)$p['is_active'] === 1) ? 'Attivo' : 'Disattivo'; ?>
|
||||
</span>
|
||||
</td>
|
||||
<td class="text-nowrap">
|
||||
<button class="btn btn-sm btn-warning"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#editPlanModal"
|
||||
onclick='fillEditPlanModal(<?php echo json_encode([
|
||||
"id" => (int)$p["id"],
|
||||
"code" => $p["code"],
|
||||
"name" => $p["name"],
|
||||
"description" => $p["description"],
|
||||
"stripe_product_id" => $p["stripe_product_id"],
|
||||
"stripe_price_id" => $p["stripe_price_id"],
|
||||
"currency" => $p["currency"],
|
||||
"unit_amount" => (int)$p["unit_amount"],
|
||||
"interval" => $p["interval"],
|
||||
"interval_count" => (int)$p["interval_count"],
|
||||
"trial_days" => (int)$p["trial_days"],
|
||||
"is_active" => (int)$p["is_active"],
|
||||
]); ?>)'>
|
||||
<i class="bx bx-edit"></i>
|
||||
</button>
|
||||
|
||||
<?php if ((int)$p['is_active'] === 1): ?>
|
||||
<form method="POST" style="display:inline;" onsubmit="return confirm('Disattivare questo piano?');">
|
||||
<input type="hidden" name="action" value="disable_plan">
|
||||
<input type="hidden" name="id" value="<?php echo (int)$p['id']; ?>">
|
||||
<button class="btn btn-sm btn-danger" type="submit" title="Disattiva">
|
||||
<i class="bx bx-power-off"></i>
|
||||
</button>
|
||||
</form>
|
||||
<?php else: ?>
|
||||
<form method="POST" style="display:inline;" onsubmit="return confirm('Riattivare questo piano?');">
|
||||
<input type="hidden" name="action" value="enable_plan">
|
||||
<input type="hidden" name="id" value="<?php echo (int)$p['id']; ?>">
|
||||
<button class="btn btn-sm btn-success" type="submit" title="Riattiva">
|
||||
<i class="bx bx-check-circle"></i>
|
||||
</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 text-muted small">
|
||||
<strong>Nota:</strong> `unit_amount` è in centesimi (es. 2990 = 29,90 EUR)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="overlay toggle-icon"></div>
|
||||
<a href="javaScript:;" class="back-to-top"><i class='bx bxs-up-arrow-alt'></i></a>
|
||||
<?php include('include/footer.php'); ?>
|
||||
</div>
|
||||
|
||||
<?php include('jsinclude.php'); ?>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#plansTable').DataTable({
|
||||
"language": {
|
||||
"url": "//cdn.datatables.net/plug-ins/1.10.25/i18n/Italian.json"
|
||||
},
|
||||
"pageLength": 10,
|
||||
"lengthMenu": [10, 25, 50, 100],
|
||||
"order": [
|
||||
[1, "asc"]
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
function fillEditPlanModal(p) {
|
||||
document.getElementById('edit_id').value = p.id;
|
||||
document.getElementById('edit_code').value = p.code || '';
|
||||
document.getElementById('edit_name').value = p.name || '';
|
||||
document.getElementById('edit_description').value = p.description || '';
|
||||
document.getElementById('edit_stripe_product_id').value = p.stripe_product_id || '';
|
||||
document.getElementById('edit_stripe_price_id').value = p.stripe_price_id || '';
|
||||
document.getElementById('edit_currency').value = p.currency || 'EUR';
|
||||
document.getElementById('edit_unit_amount').value = (p.unit_amount ?? 0);
|
||||
document.getElementById('edit_interval').value = p.interval || 'month';
|
||||
document.getElementById('edit_interval_count').value = p.interval_count || 1;
|
||||
document.getElementById('edit_trial_days').value = p.trial_days || 0;
|
||||
document.getElementById('edit_is_active').checked = (parseInt(p.is_active, 10) === 1);
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- ADD MODAL -->
|
||||
<div class="modal fade" id="addPlanModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Nuovo Piano</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Chiudi"></button>
|
||||
</div>
|
||||
|
||||
<form method="POST">
|
||||
<div class="modal-body">
|
||||
<input type="hidden" name="action" value="add_plan">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Code *</label>
|
||||
<input type="text" name="code" class="form-control" required>
|
||||
</div>
|
||||
<div class="col-md-8 mb-3">
|
||||
<label class="form-label">Nome *</label>
|
||||
<input type="text" name="name" class="form-control" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Descrizione</label>
|
||||
<textarea name="description" class="form-control" rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Valuta</label>
|
||||
<input type="text" name="currency" class="form-control" value="EUR" maxlength="3">
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Unit amount (centesimi) *</label>
|
||||
<input type="number" name="unit_amount" class="form-control" min="0" value="0" required>
|
||||
<small class="text-muted">es: 2990 = 29,90</small>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Trial days</label>
|
||||
<input type="number" name="trial_days" class="form-control" min="0" value="0">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Interval</label>
|
||||
<select name="interval" class="form-control">
|
||||
<option value="day">day</option>
|
||||
<option value="week">week</option>
|
||||
<option value="month" selected>month</option>
|
||||
<option value="year">year</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Interval count</label>
|
||||
<input type="number" name="interval_count" class="form-control" min="1" value="1">
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Stato</label>
|
||||
<div class="form-check form-switch mt-2">
|
||||
<input class="form-check-input" type="checkbox" name="is_active" value="1" checked>
|
||||
<label class="form-check-label">Attivo</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Stripe product id</label>
|
||||
<input type="text" name="stripe_product_id" class="form-control" placeholder="prod_... (optional)">
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Stripe price id *</label>
|
||||
<input type="text" name="stripe_price_id" class="form-control" placeholder="price_..." required>
|
||||
<small class="text-muted">Obbligatorio (NOT NULL)</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Chiudi</button>
|
||||
<button type="submit" class="btn btn-primary">Crea Piano</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- EDIT MODAL -->
|
||||
<div class="modal fade" id="editPlanModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Modifica Piano</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Chiudi"></button>
|
||||
</div>
|
||||
|
||||
<form method="POST">
|
||||
<div class="modal-body">
|
||||
<input type="hidden" name="action" value="edit_plan">
|
||||
<input type="hidden" name="id" id="edit_id">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Code *</label>
|
||||
<input type="text" name="code" id="edit_code" class="form-control" required>
|
||||
</div>
|
||||
<div class="col-md-8 mb-3">
|
||||
<label class="form-label">Nome *</label>
|
||||
<input type="text" name="name" id="edit_name" class="form-control" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Descrizione</label>
|
||||
<textarea name="description" id="edit_description" class="form-control" rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Valuta</label>
|
||||
<input type="text" name="currency" id="edit_currency" class="form-control" maxlength="3">
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Unit amount (centesimi) *</label>
|
||||
<input type="number" name="unit_amount" id="edit_unit_amount" class="form-control" min="0" required>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Trial days</label>
|
||||
<input type="number" name="trial_days" id="edit_trial_days" class="form-control" min="0">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Interval</label>
|
||||
<select name="interval" id="edit_interval" class="form-control">
|
||||
<option value="day">day</option>
|
||||
<option value="week">week</option>
|
||||
<option value="month">month</option>
|
||||
<option value="year">year</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Interval count</label>
|
||||
<input type="number" name="interval_count" id="edit_interval_count" class="form-control" min="1">
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Stato</label>
|
||||
<div class="form-check form-switch mt-2">
|
||||
<input class="form-check-input" type="checkbox" name="is_active" id="edit_is_active" value="1">
|
||||
<label class="form-check-label">Attivo</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Stripe product id</label>
|
||||
<input type="text" name="stripe_product_id" id="edit_stripe_product_id" class="form-control">
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Stripe price id *</label>
|
||||
<input type="text" name="stripe_price_id" id="edit_stripe_price_id" class="form-control" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Chiudi</button>
|
||||
<button type="submit" class="btn btn-primary">Salva</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user