37338-vm/index.php
2026-03-01 17:31:49 +00:00

1184 lines
65 KiB
PHP

<?php
require_once 'WorkflowEngine.php';
$workflowEngine = new WorkflowEngine();
$searchTerm = $_GET['search'] ?? null;
$groupId = isset($_GET['group_id']) && $_GET['group_id'] !== '' ? (int)$_GET['group_id'] : null;
$activeProcessId = isset($_GET['active_process_id']) && $_GET['active_process_id'] !== '' ? (int)$_GET['active_process_id'] : null;
// Handle toggling of the active process filter
if (isset($_GET['active_process_id']) && $_GET['active_process_id'] == @$_SESSION['last_active_process_id']) {
unset($_GET['active_process_id']);
$activeProcessId = null;
$redirectUrl = "index.php";
$queryParams = [];
if ($groupId) {
$queryParams['group_id'] = $groupId;
}
if ($searchTerm) {
$queryParams['search'] = $searchTerm;
}
if (!empty($queryParams)) {
$redirectUrl .= "?" . http_build_query($queryParams);
}
header("Location: " . $redirectUrl);
exit;
}
$_SESSION['last_active_process_id'] = $activeProcessId;
$meetingFilterGroupId = isset($_GET['meeting_filter_group_id']) && $_GET['meeting_filter_group_id'] !== '' ? (int)$_GET['meeting_filter_group_id'] : null;
$meetingFilterDatetime = $_GET['meeting_filter_datetime'] ?? null;
// Handle toggling of the active meeting filter
if ($meetingFilterGroupId && $meetingFilterDatetime &&
$meetingFilterGroupId == ($_SESSION['last_meeting_filter_group_id'] ?? null) &&
$meetingFilterDatetime == ($_SESSION['last_meeting_filter_datetime'] ?? null)) {
unset($_GET['meeting_filter_group_id']);
unset($_GET['meeting_filter_datetime']);
$redirectUrl = "index.php";
// Re-build the query string without the meeting filter parameters
$queryParams = $_GET;
if (!empty($queryParams)) {
$redirectUrl .= "?" . http_build_query($queryParams);
}
header("Location: " . $redirectUrl);
exit;
}
$_SESSION['last_meeting_filter_group_id'] = $meetingFilterGroupId;
$_SESSION['last_meeting_filter_datetime'] = $meetingFilterDatetime;
$matrixData = $workflowEngine->getDashboardMatrix($searchTerm, $groupId, $activeProcessId, $meetingFilterGroupId, $meetingFilterDatetime);
$people = $matrixData['people'];
$processes = $matrixData['definitions'];
$instances = $matrixData['instances'];
$spotkania_cols = $matrixData['spotkania_cols'];
$bni_groups = $matrixData['bni_groups'];
$all_functions = $matrixData['all_functions'];
$status_colors = [
'none' => 'secondary',
'negative' => 'danger',
'in_progress' => 'warning',
'positive' => 'success',
'present' => 'success',
'absent' => 'danger',
'substitute' => 'warning',
];
?>
<?php include '_header.php'; ?>
<?php include '_navbar.php'; ?>
<div class="container-fluid">
<div class="row">
<?php include '_sidebar.php'; ?>
<main id="main-content" class="col-md-9 col-lg-10 px-md-4">
<?php if (isset($_SESSION['success_message'])): ?>
<div class="alert alert-success alert-dismissible fade show mt-3" role="alert">
<?= $_SESSION['success_message']; ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php unset($_SESSION['success_message']); ?>
<?php endif; ?>
<?php if (isset($_SESSION['error_message'])): ?>
<div class="alert alert-danger alert-dismissible fade show mt-3" role="alert">
<?= $_SESSION['error_message']; ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php unset($_SESSION['error_message']); ?>
<?php endif; ?>
<div class="d-flex justify-content-between align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2"><?= t('dashboard.title', 'Pulpit nawigacyjny') ?></h1>
<div class="btn-toolbar mb-2 mb-md-0">
<div class="btn-group me-2" id="bulk-actions-group" style="display: none;">
<button type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
<?= t('dashboard.bulk_actions', 'Akcje zbiorcze') ?>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" data-bs-toggle="modal" data-bs-target="#bulkStatusModal"><?= t('dashboard.bulk_status_update', 'Zbiorcza aktualizacja statusu') ?></a></li>
<li><a class="dropdown-item" href="#" data-bs-toggle="modal" data-bs-target="#bulkEventModal"><?= t('dashboard.bulk_add_event', 'Zbiorcze dodawanie zdarzenia') ?></a></li>
<li><a class="dropdown-item" href="#" data-bs-toggle="modal" data-bs-target="#bulkInitModal"><?= t('dashboard.bulk_init_instances', 'Zbiorcza inicjalizacja instancji') ?></a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#" id="bulkPrintBadge"><?= t('dashboard.bulk_print_badge', 'Drukuj identyfikatory') ?></a></li>
<li><a class="dropdown-item" href="#" id="bulkPrintAttendance"><?= t('dashboard.bulk_print_attendance', 'Drukuj listę obecności') ?></a></li>
</ul>
</div>
<button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#createPersonModal">
<?= t('dashboard.create_person', 'Dodaj osobę') ?>
</button>
</div>
</div>
<?php
// Define process groups
// Show all processes from the DB directly.
$inne_procesy_cols = $processes;
?>
<div class="mb-3">
<label class="form-label"><?= t('dashboard.filter_by_group', 'Filtruj wg grupy:') ?></label>
<div class="btn-group" role="group" aria-label="Group Filter">
<a href="index.php?<?= http_build_query(array_merge($_GET, ['group_id' => ''])) ?>" class="btn btn-outline-primary <?= !$groupId ? 'active-filter' : '' ?>"><?= t('dashboard.all_groups', 'Wszystkie grupy') ?></a>
<?php foreach ($bni_groups as $group): ?>
<a href="index.php?<?= http_build_query(array_merge($_GET, ['group_id' => $group['id']])) ?>" class="btn btn-outline-primary <?= ($groupId == $group['id']) ? 'active-filter' : '' ?>">
<?= htmlspecialchars($group['name']) ?>
</a>
<?php endforeach; ?>
</div>
</div>
<div class="table-responsive">
<table class="table table-bordered table-sm">
<thead class="table-light">
<tr class="text-center">
<th rowspan="2" class="align-middle"><input type="checkbox" id="selectAll"></th>
<th rowspan="2" class="align-middle"><?= t('dashboard.person', 'Osoba') ?></th>
<?php if (!empty($spotkania_cols)): ?>
<th colspan="<?= count($spotkania_cols) ?>"><?= t('dashboard.meetings', 'Spotkania') ?></th>
<?php endif; ?>
<?php if (!empty($inne_procesy_cols)): ?>
<th colspan="<?= count($processes) ?>"><?= t('dashboard.other_processes', 'Inne procesy') ?></th>
<?php endif; ?>
</tr>
<tr class="text-center">
<?php foreach ($spotkania_cols as $col):
$isMeetingFilterActive = ($meetingFilterGroupId == $col['group_id'] && $meetingFilterDatetime == ($col['meetings'][0] ?? null));
?>
<th data-group-id="<?= $col['group_id'] ?>" data-meetings='<?= json_encode($col['meetings'] ?? []) ?>' class="<?= $isMeetingFilterActive ? 'active-filter' : '' ?>">
<a href="#" class="text-decoration-none text-dark meeting-filter-link">
<div class="d-flex justify-content-center align-items-center">
<button class="btn btn-sm btn-outline-secondary meeting-nav-btn meeting-prev-btn"><i class="bi bi-chevron-left"></i></button>
<div class="mx-2 text-center">
<?= htmlspecialchars($col['group_name']) ?><br>
<small class="meeting-date"></small>
</div>
<button class="btn btn-sm btn-outline-secondary meeting-nav-btn meeting-next-btn"><i class="bi bi-chevron-right"></i></button>
</div>
</a>
</th>
<?php endforeach; ?>
<?php foreach ($processes as $col): ?>
<?php
$filterParams = $_GET;
$filterParams['active_process_id'] = $col['id'];
$link = 'index.php?' . http_build_query($filterParams);
$isActive = $activeProcessId == $col['id'];
?>
<th class="<?= $isActive ? 'active-filter' : '' ?>">
<a href="<?= $link ?>" class="text-decoration-none text-dark"><?= htmlspecialchars($col['name']) ?></a>
</th>
<?php endforeach; ?>
</tr>
</thead>
<tbody>
<?php foreach ($people as $person): ?>
<tr data-group-id="<?= $person['bni_group_id'] ?>">
<td class="text-center align-middle"><input type="checkbox" class="person-checkbox" name="person_ids[]" value="<?= $person['id'] ?>"></td>
<td class="person-cell">
<div class="person-main">
<div class="person-name"><?= htmlspecialchars($person['first_name'] . ' ' . $person['last_name']) ?></div>
<div class="person-details">
<span class="d-block"><?= htmlspecialchars($person['company_name'] ?? '') ?></span>
<span class="d-block"><?= htmlspecialchars($person['industry'] ?? '') ?></span>
<span><?= htmlspecialchars(ucfirst($person['role'])) ?></span>
<?php if ($person['role'] === 'member' && !empty($person['bni_group_name'])): ?>
<span class="person-group">, Grupa: <?= htmlspecialchars($person['bni_group_name']) ?></span>
<?php endif; ?>
</div>
</div>
<div class="person-actions">
<div class="status-dots">
<?php if ($person['role'] === 'member'): ?>
<span class="status-dot <?= !empty($person['gains_sheet_path']) ? 'bg-success' : 'bg-danger' ?>" title="GAINS Sheet"></span>
<span class="status-dot <?= !empty($person['top_wanted_contacts_path']) ? 'bg-success' : 'bg-danger' ?>" title="Top Wanted Contacts"></span>
<span class="status-dot <?= !empty($person['top_owned_contacts_path']) ? 'bg-success' : 'bg-danger' ?>" title="Top Owned Contacts"></span>
<?php endif; ?>
</div>
<button class="btn btn-sm btn-secondary edit-btn" data-bs-toggle="modal" data-bs-target="#editPersonModal"
data-person-id="<?= $person['id'] ?>"
data-person-name="<?= htmlspecialchars($person['first_name'] . ' ' . $person['last_name']) ?>">
Edit
</button>
</div>
</td>
<?php // Spotkania Columns ?>
<?php foreach ($spotkania_cols as $col): ?>
<td class="text-center align-middle meeting-cell" data-group-id="<?= $col['group_id'] ?>">
<?php
// Use the new isMemberOfGroup function to determine the default status
$isMember = $workflowEngine->isMemberOfGroup($person['id'], $col['group_id']);
$status = $isMember ? 'present' : 'none';
// The meeting date will be determined by JS, we will add it to the data attribute
// The initial meeting date is the first one in the list.
$meeting_datetime = $col['meetings'][0] ?? '';
$color = $status_colors[$status] ?? 'secondary';
?>
<span class="badge rounded-circle bg-<?= $color ?> meeting-dot"
style="width: 20px; height: 20px; display: inline-block; cursor: pointer;"
data-person-id="<?= $person['id'] ?>"
data-person-name="<?= htmlspecialchars($person['first_name'] . ' ' . $person['last_name']) ?>"
data-bni-group-id="<?= $col['group_id'] ?>"
data-meeting-datetime="<?= $meeting_datetime ?>"
data-current-status="<?= $status ?>"
title="Status: <?= ucfirst($status) ?>"></span>
</td>
<?php endforeach; ?>
<?php // Inne Procesy Columns ?>
<?php foreach ($processes as $process):
$instance = $instances[$person['id']][$process['id']] ?? null;
$status = $instance ? $instance['computed_status'] : 'none';
$color = $status_colors[$status] ?? 'secondary';
$lastActivity = $instance && $instance['last_activity_at'] ? date('d/m/y', strtotime($instance['last_activity_at'])) : '';
?>
<td class="text-center align-middle" data-bs-toggle="modal" data-bs-target="#instanceModal" data-person-id="<?= $person['id'] ?>" data-process-id="<?= $process['id'] ?>">
<span class="badge rounded-circle bg-<?= $color ?>" style="width: 20px; height: 20px; display: inline-block;" title="<?= ucfirst($status) ?>">&nbsp;</span>
<small class="text-muted d-block"><?= $lastActivity ?></small>
</td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</main>
</div>
</div>
<!-- Edit Person Modal -->
<div class="modal fade" id="editPersonModal" tabindex="-1" aria-labelledby="editPersonModalLabel" aria-hidden="true">
<div class="modal-dialog modal-fullscreen-xl">
<div class="modal-content">
<form id="editPersonForm" action="_update_person.php" method="post" enctype="multipart/form-data">
<div class="modal-header">
<h5 class="modal-title" id="editPersonModalLabel"><?= t('modal.edit_person', 'Edytuj osobę') ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Zamknij"></button>
</div>
<div class="modal-body">
<input type="hidden" name="id" id="editPersonId">
<div class="row">
<div class="col-md-4">
<div class="mb-3">
<label for="editFirstName" class="form-label"><?= t('form.first_name', 'Imię') ?></label>
<input type="text" class="form-control" id="editFirstName" name="first_name" required>
</div>
<div class="mb-3">
<label for="editLastName" class="form-label"><?= t('form.last_name', 'Nazwisko') ?></label>
<input type="text" class="form-control" id="editLastName" name="last_name" required>
</div>
<div class="mb-3">
<label for="editPhone" class="form-label"><?= t('form.phone', 'Numer telefonu') ?></label>
<input type="text" class="form-control" id="editPhone" name="phone">
</div>
<div class="mb-3">
<label for="editEmail" class="form-label"><?= t('form.email', 'Email (login)') ?></label>
<input type="email" class="form-control" id="editEmail" name="email">
</div>
<div class="mb-3">
<label for="editPassword" class="form-label"><?= t('form.new_password', 'Nowe hasło') ?></label>
<input type="password" class="form-control" id="editPassword" name="password">
<small class="form-text text-muted">Pozostaw puste, jeśli nie chcesz zmieniać hasła.</small>
</div>
</div>
<div class="col-md-4">
<div class="mb-3">
<label for="editRole" class="form-label"><?= t('form.role', 'Rola') ?></label>
<select class="form-select" id="editRole" name="role" required>
<option value="admin">Admin</option>
<option value="member">Członek</option>
<option value="guest">Gość</option>
<option value="team_member">Pracownik Biura</option>
</select>
</div>
<div class="mb-3" id="edit-group-selection-div" style="display: none;">
<label for="editBniGroup" class="form-label"><?= t('form.group', 'Grupa') ?></label>
<select class="form-select" id="editBniGroup" name="bni_group_id">
<option value="">Wybierz grupę...</option>
<?php foreach ($bni_groups as $group): ?>
<option value="<?= $group['id'] ?>"><?= htmlspecialchars($group['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label for="editRoles" class="form-label"><?= t('form.functions', 'Funkcje') ?></label>
<select class="form-select" id="editRoles" name="functions[]" multiple size="5">
<!-- Opcje zostaną wstawione przez JavaScript -->
</select>
</div>
<div class="mb-3">
<label for="editCompanyName" class="form-label"><?= t('form.company_name', 'Nazwa firmy') ?></label>
<input type="text" class="form-control" id="editCompanyName" name="company_name">
</div>
</div>
<div class="col-md-4">
<div class="mb-3">
<label for="editNip" class="form-label"><?= t('form.nip', 'NIP') ?></label>
<input type="text" class="form-control" id="editNip" name="nip">
</div>
<div class="mb-3">
<label for="editIndustry" class="form-label"><?= t('form.industry', 'Branża') ?></label>
<input type="text" class="form-control" id="editIndustry" name="industry">
</div>
<div class="mb-3">
<label for="editCompanySize" class="form-label"><?= t('form.company_size', 'Wielkość firmy / Przychody') ?></label>
<input type="text" class="form-control" id="editCompanySize" name="company_size_revenue">
</div>
<div class="mb-3">
<label for="editBusinessDescription" class="form-label"><?= t('form.business_description', 'Opis działalności') ?></label>
<textarea class="form-control" id="editBusinessDescription" name="business_description" rows="3"></textarea>
</div>
</div>
</div>
<div class="row member-only-fields" style="display: none;">
<hr class="mt-3">
<div class="col-md-6">
<h5>Pliki firmowe</h5>
<div class="mb-3">
<label for="editCompanyLogo" class="form-label"><?= t('form.company_logo', 'Logo firmy') ?></label>
<input class="form-control" type="file" id="editCompanyLogo" name="company_logo">
<small id="editCompanyLogoPath" class="form-text text-muted"></small>
</div>
<div class="mb-3">
<label for="editPersonPhoto" class="form-label"><?= t('form.person_photo', 'Zdjęcie osoby') ?></label>
<input class="form-control" type="file" id="editPersonPhoto" name="person_photo">
<small id="editPersonPhotoPath" class="form-text text-muted"></small>
</div>
</div>
<div class="col-md-6">
<h5>Dokumenty członkowskie</h5>
<div class="mb-3">
<label for="editGainsSheet" class="form-label"><?= t('form.gains_sheet', 'Arkusz GAINS') ?></label>
<input class="form-control" type="file" id="editGainsSheet" name="gains_sheet">
<small id="editGainsSheetPath" class="form-text text-muted"></small>
</div>
<div class="mb-3">
<label for="editTopWanted" class="form-label"><?= t('form.top_wanted', 'Lista TOP poszukiwanych kontaktów') ?></label>
<input class="form-control" type="file" id="editTopWanted" name="top_wanted_contacts">
<small id="editTopWantedPath" class="form-text text-muted"></small>
</div>
<div class="mb-3">
<label for="editTopOwned" class="form-label"><?= t('form.top_owned', 'Lista TOP posiadanych kontaktów') ?></label>
<input class="form-control" type="file" id="editTopOwned" name="top_owned_contacts">
<small id="editTopOwnedPath" class="form-text text-muted"></small>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?= t('modal.close', 'Zamknij') ?></button>
<button type="submit" class="btn btn-primary"><?= t('modal.save_changes', 'Zapisz zmiany') ?></button>
<button type="button" class="btn btn-danger ms-auto" id="deleteUserBtn" data-bs-toggle="modal" data-bs-target="#deletePersonModal">Usuń</button>
</div>
</form>
</div>
</div>
</div>
<!-- <?= t('dashboard.create_person', 'Dodaj osobę') ?> Modal -->
<div class="modal fade" id="createPersonModal" tabindex="-1" aria-labelledby="createPersonModalLabel" aria-hidden="true">
<div class="modal-dialog modal-fullscreen-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="createPersonModalLabel"><?= t('dashboard.create_person', 'Dodaj osobę') ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="createPersonForm" action="_create_person.php" method="post" enctype="multipart/form-data">
<div class="row">
<div class="col-md-4">
<div class="mb-3">
<label for="createFirstName" class="form-label"><?= t('form.first_name', 'Imię') ?> <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="createFirstName" name="first_name" required>
</div>
<div class="mb-3">
<label for="createLastName" class="form-label"><?= t('form.last_name', 'Nazwisko') ?> <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="createLastName" name="last_name" required>
</div>
<div class="mb-3">
<label for="createPhone" class="form-label"><?= t('form.phone', 'Numer telefonu') ?></label>
<input type="text" class="form-control" id="createPhone" name="phone">
</div>
<div class="mb-3">
<label for="createEmail" class="form-label"><?= t('form.email', 'Email (login)') ?> <span class="text-danger">*</span></label>
<input type="email" class="form-control" id="createEmail" name="email" required>
</div>
<div class="mb-3">
<label for="createPassword" class="form-label"><?= t('form.password', 'Hasło') ?> <span class="text-danger">*</span></label>
<input type="password" class="form-control" id="createPassword" name="password" required>
</div>
</div>
<div class="col-md-4">
<div class="mb-3">
<label for="createRole" class="form-label"><?= t('form.role', 'Rola') ?></label>
<select class="form-select" id="createRole" name="role" required>
<option value="admin">Admin</option>
<option value="member" selected>Członek</option>
<option value="guest">Gość</option>
<option value="team_member">Pracownik Biura</option>
</select>
</div>
<div class="mb-3" id="create-group-selection-div">
<label for="createBniGroup" class="form-label"><?= t('form.group', 'Grupa') ?></label>
<select class="form-select" id="createBniGroup" name="bni_group_id">
<option value="">Wybierz grupę...</option>
<?php foreach ($bni_groups as $group): ?>
<option value="<?= $group['id'] ?>"><?= htmlspecialchars($group['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label for="createRoles" class="form-label"><?= t('form.functions', 'Funkcje') ?></label>
<select class="form-select" id="createRoles" name="functions[]" multiple size="5">
<?php foreach ($all_functions as $function): ?>
<option value="<?= $function['id'] ?>"><?= htmlspecialchars($function['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label for="createCompanyName" class="form-label"><?= t('form.company_name', 'Nazwa firmy') ?></label>
<input type="text" class="form-control" id="createCompanyName" name="company_name">
</div>
</div>
<div class="col-md-4">
<div class="mb-3">
<label for="createNip" class="form-label"><?= t('form.nip', 'NIP') ?></label>
<input type="text" class="form-control" id="createNip" name="nip">
</div>
<div class="mb-3">
<label for="createIndustry" class="form-label"><?= t('form.industry', 'Branża') ?></label>
<input type="text" class="form-control" id="createIndustry" name="industry">
</div>
<div class="mb-3">
<label for="createCompanySize" class="form-label"><?= t('form.company_size', 'Wielkość firmy / Przychody') ?></label>
<input type="text" class="form-control" id="createCompanySize" name="company_size_revenue">
</div>
<div class="mb-3">
<label for="createBusinessDescription" class="form-label"><?= t('form.business_description', 'Opis działalności') ?></label>
<textarea class="form-control" id="createBusinessDescription" name="business_description" rows="3"></textarea>
</div>
</div>
</div>
<div class="row member-only-fields" style="display: none;">
<hr class="mt-3">
<div class="col-md-6">
<h5>Pliki firmowe</h5>
<div class="mb-3">
<label for="createCompanyLogo" class="form-label"><?= t('form.company_logo', 'Logo firmy') ?></label>
<input class="form-control" type="file" id="createCompanyLogo" name="company_logo">
</div>
<div class="mb-3">
<label for="createPersonPhoto" class="form-label"><?= t('form.person_photo', 'Zdjęcie osoby') ?></label>
<input class="form-control" type="file" id="createPersonPhoto" name="person_photo">
</div>
</div>
<div class="col-md-6">
<h5>Dokumenty członkowskie</h5>
<div class="mb-3">
<label for="createGainsSheet" class="form-label"><?= t('form.gains_sheet', 'Arkusz GAINS') ?></label>
<input class="form-control" type="file" id="createGainsSheet" name="gains_sheet">
</div>
<div class="mb-3">
<label for="createTopWanted" class="form-label"><?= t('form.top_wanted', 'Lista TOP poszukiwanych kontaktów') ?></label>
<input class="form-control" type="file" id="createTopWanted" name="top_wanted_contacts">
</div>
<div class="mb-3">
<label for="createTopOwned" class="form-label"><?= t('form.top_owned', 'Lista TOP posiadanych kontaktów') ?></label>
<input class="form-control" type="file" id="createTopOwned" name="top_owned_contacts">
</div>
</div>
</div>
<button type="submit" class="btn btn-primary mt-3"><?= t('dashboard.create_person', 'Dodaj osobę') ?></button>
</form>
</div>
</div>
</div>
</div>
<!-- Delete Person Modal -->
<div class="modal fade" id="deletePersonModal" tabindex="-1" aria-labelledby="deletePersonModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="deletePersonModalLabel"><?= t('modal.confirm_delete', 'Potwierdź usunięcie') ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Zamknij"></button>
</div>
<div class="modal-body">
Czy na pewno chcesz usunąć użytkownika <strong id="personNameToDelete"></strong>? Tej operacji nie można cofnąć.
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?= t('modal.cancel', 'Anuluj') ?></button>
<button type="button" class="btn btn-danger" id="confirmDeleteBtn">Tak, usuń</button>
</div>
</div>
</div>
</div>
<!-- Meeting Attendance Modal -->
<div class="modal fade" id="meetingAttendanceModal" tabindex="-1" aria-labelledby="meetingAttendanceModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<form id="meetingAttendanceForm">
<div class="modal-header">
<h5 class="modal-title" id="meetingAttendanceModalLabel"><?= t('modal.update_attendance', 'Aktualizuj obecność') ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<input type="hidden" name="person_id" id="meetingPersonId">
<input type="hidden" name="bni_group_id" id="meetingGroupId">
<input type="hidden" name="meeting_date" id="meetingDate">
<p><strong>Person:</strong> <span id="meetingPersonName"></span></p>
<div class="mb-3">
<label for="attendanceStatus" class="form-label"><?= t('form.status', 'Status') ?></label>
<select class="form-select" id="attendanceStatus" name="attendance_status">
<option value="present">Present</option>
<option value="absent">Absent</option>
<option value="substitute">Substitute</option>
<option value="none">None</option>
</select>
</div>
<div class="mb-3" id="guestSurveySection" style="display: none;">
<label class="form-label"><?= t('form.guest_survey', 'Ankieta gościa') ?></label>
<div class="form-check">
<input class="form-check-input" type="radio" name="guest_survey" id="guestSurvey1" value="1">
<label class="form-check-label" for="guestSurvey1">1 (Positive)</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="guest_survey" id="guestSurvey2" value="2">
<label class="form-check-label" for="guestSurvey2">2 (Neutral)</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="guest_survey" id="guestSurvey3" value="3">
<label class="form-check-label" for="guestSurvey3">3 (Negative)</label>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?= t('modal.close', 'Zamknij') ?></button>
<button type="submit" class="btn btn-primary"><?= t('modal.save_changes', 'Zapisz zmiany') ?></button>
</div>
</form>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
const meetingModal = new bootstrap.Modal(document.getElementById('meetingAttendanceModal'));
const meetingForm = document.getElementById('meetingAttendanceForm');
const meetingPersonName = document.getElementById('meetingPersonName');
const meetingPersonId = document.getElementById('meetingPersonId');
const meetingGroupId = document.getElementById('meetingGroupId');
const meetingDateInput = document.getElementById('meetingDate');
const attendanceStatus = document.getElementById('attendanceStatus');
const guestSurveySection = document.getElementById('guestSurveySection');
const statusColors = {
'none': 'secondary',
'absent': 'danger',
'substitute': 'warning',
'present': 'success',
};
function updateDot(dot, status) {
const color = statusColors[status] || 'secondary';
dot.className = `badge rounded-circle bg-${color} meeting-dot`;
dot.dataset.currentStatus = status;
dot.title = `Status: ${status.charAt(0).toUpperCase() + status.slice(1)}`;
}
function fetchAndUpdateAllDotsForGroup(groupId, meetingDate) {
fetch(`_get_meeting_attendance.php?group_id=${groupId}&meeting_date=${meetingDate}`)
.then(response => response.json())
.then(data => {
if (data.success) {
// Update the data-meeting-datetime for all dots in the column
document.querySelectorAll(`.meeting-dot[data-bni-group-id='${groupId}']`).forEach(dot => {
dot.dataset.meetingDatetime = meetingDate;
const personId = dot.dataset.personId;
const personRow = dot.closest('tr');
const personGroupId = personRow.dataset.groupId;
const isMember = personGroupId == groupId;
let defaultStatus = isMember ? 'present' : 'none';
let status = defaultStatus;
if (data.attendance[personId]) {
status = data.attendance[personId].attendance_status;
}
updateDot(dot, status);
});
}
});
}
// Event delegation for meeting dot clicks
document.querySelector('tbody').addEventListener('click', function(event) {
if (!event.target.classList.contains('meeting-dot')) {
return;
}
const dot = event.target;
const personId = dot.dataset.personId;
const personName = dot.dataset.personName;
const bniGroupId = dot.dataset.bniGroupId;
const meetingDatetime = dot.dataset.meetingDatetime;
const currentStatus = dot.dataset.currentStatus || 'none';
// The person's own group is on the TR element
const personGroupId = dot.closest('tr').dataset.groupId;
const isMember = personGroupId == bniGroupId;
// Set form values
meetingPersonId.value = personId;
meetingPersonName.textContent = personName;
meetingGroupId.value = bniGroupId;
meetingDateInput.value = meetingDatetime;
attendanceStatus.value = currentStatus;
// Show/hide guest survey
guestSurveySection.style.display = !isMember ? 'block' : 'none';
// Clear previous survey selection
document.querySelectorAll('input[name="guest_survey"]').forEach(radio => radio.checked = false);
// Fetch full details to populate the modal correctly, including saved status and survey
fetch(`_get_meeting_details.php?person_id=${personId}&bni_group_id=${bniGroupId}&meeting_datetime=${meetingDatetime}`)
.then(response => response.json())
.then(data => {
if(data.success) {
attendanceStatus.value = data.details.attendance_status;
if(data.details.guest_survey) {
const surveyRadio = document.getElementById('guestSurvey' + data.details.guest_survey);
if(surveyRadio) surveyRadio.checked = true;
}
}
meetingModal.show();
})
.catch(err => {
console.error('Error fetching meeting details:', err);
// Still show modal with defaults if fetch fails
meetingModal.show();
});
});
meetingForm.addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
const personId = formData.get('person_id');
const bniGroupId = formData.get('bni_group_id');
fetch('_update_meeting_attendance.php', {
method: 'POST',
body: formData
})
.then(response => {
// We need to handle the body carefully to avoid "body already consumed" errors.
// We'll get the text first, then try to parse it.
return response.text().then(text => {
// If the response wasn't OK, we always treat it as an error.
if (!response.ok) {
try {
// See if the error response is JSON
const data = JSON.parse(text);
const errorMessage = data.error || 'Unknown server error.';
const correlationId = data.correlation_id || 'N/A';
throw new Error(`Server Error: ${errorMessage} (Correlation ID: ${correlationId})`);
} catch (e) {
// If it's not JSON, throw the raw text.
throw new Error('Server error: ' + response.status + ' ' + response.statusText + '. Response: ' + text.substring(0, 200));
}
}
// If the response was OK, parse the text as JSON.
// It might still fail if the OK response is not valid JSON.
try {
return JSON.parse(text);
} catch (e) {
throw new Error('Failed to parse successful response as JSON. Raw response: ' + text.substring(0, 200));
}
});
})
.then(data => {
if (data.success) {
meetingModal.hide();
// Find the correct dot to update. Note the attribute is data-bni-group-id
const dot = document.querySelector(`.meeting-dot[data-person-id='${personId}'][data-bni-group-id='${bniGroupId}']`);
if (dot) {
updateDot(dot, formData.get('attendance_status'));
}
} else {
// Handle structured errors from a successful (e.g. 200) response
const errorMessage = data.error || 'An unknown error occurred.';
const correlationId = data.correlation_id || 'N/A';
alert(`Error: ${errorMessage}\nCorrelation ID: ${correlationId}`);
}
})
.catch(error => {
console.error('Fetch Error:', error);
alert('An error occurred while submitting the form. ' + error.message);
});
});
// Initial load and navigation for meeting attendance
document.querySelectorAll('th[data-group-id][data-meetings]').forEach(headerCell => {
const groupId = headerCell.dataset.groupId;
let meetings = JSON.parse(headerCell.dataset.meetings);
let currentIndex = 0;
function updateMeetingView() {
if (meetings.length > 0) {
const currentMeetingDate = meetings[currentIndex];
headerCell.querySelector('.meeting-date').textContent = new Date(currentMeetingDate).toLocaleDateString('pl-PL', { day: '2-digit', month: '2-digit', year: 'numeric' });
fetchAndUpdateAllDotsForGroup(groupId, currentMeetingDate);
} else {
headerCell.querySelector('.meeting-date').textContent = 'Brak';
}
headerCell.querySelector('.meeting-prev-btn').disabled = currentIndex === 0;
headerCell.querySelector('.meeting-next-btn').disabled = currentIndex >= meetings.length - 1;
}
if (meetings.length > 0) {
updateMeetingView();
}
headerCell.querySelector('.meeting-prev-btn').addEventListener('click', function(e) {
e.stopPropagation();
if (currentIndex > 0) {
currentIndex--;
updateMeetingView();
}
});
headerCell.querySelector('.meeting-next-btn').addEventListener('click', function(e) {
e.stopPropagation();
if (currentIndex < meetings.length - 1) {
currentIndex++;
updateMeetingView();
}
});
});
// Handle meeting filter clicks
document.querySelectorAll('.meeting-filter-link').forEach(link => {
link.addEventListener('click', function(e) {
if (e.target.closest('.meeting-nav-btn')) {
return;
}
e.preventDefault();
const header = this.closest('th');
const isActive = header.classList.contains('active-filter');
const urlParams = new URLSearchParams(window.location.search);
if (isActive) {
urlParams.delete('meeting_filter_group_id');
urlParams.delete('meeting_filter_datetime');
} else {
const groupId = header.dataset.groupId;
// The meeting datetime is dynamic, so we need to get it from the elements
const firstDotInColumn = document.querySelector(`.meeting-dot[data-bni-group-id='${groupId}']`);
const meetingDatetime = firstDotInColumn ? firstDotInColumn.dataset.meetingDatetime : '';
if (groupId && meetingDatetime) {
urlParams.set('meeting_filter_group_id', groupId);
urlParams.set('meeting_filter_datetime', meetingDatetime);
}
}
window.location.href = 'index.php?' + urlParams.toString();
});
});
});
</script>
<?php include '_footer.php'; ?>
<!-- Instance Modal -->
<div class="modal fade" id="instanceModal" tabindex="-1" aria-labelledby="instanceModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="instanceModalLabel"><?= t('modal.process_details', 'Szczegóły procesu') ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<!-- Content will be loaded here via AJAX -->
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?= t('modal.close', 'Zamknij') ?></button>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
var instanceModal = document.getElementById('instanceModal');
instanceModal.addEventListener('show.bs.modal', function (event) {
var button = event.relatedTarget;
var personId = button.dataset.personId;
var processId = button.dataset.processId;
var modalBody = instanceModal.querySelector('.modal-body');
// Load content via AJAX
fetch(`_get_instance_details.php?person_id=${personId}&process_id=${processId}`)
.then(response => response.text())
.then(html => {
modalBody.innerHTML = html;
});
});
// Bulk actions
const selectAll = document.getElementById('selectAll');
const checkboxes = document.querySelectorAll('.person-checkbox');
const bulkActionsGroup = document.getElementById('bulk-actions-group');
function toggleBulkActions() {
const anyChecked = Array.from(checkboxes).some(c => c.checked);
bulkActionsGroup.style.display = anyChecked ? 'block' : 'none';
}
selectAll.addEventListener('change', function () {
checkboxes.forEach(c => c.checked = selectAll.checked);
toggleBulkActions();
});
checkboxes.forEach(c => c.addEventListener('change', toggleBulkActions));
// Pass selected people to modals
function setupBulkModal(modalId, hiddenInputId) {
const modal = document.getElementById(modalId);
modal.addEventListener('show.bs.modal', function() {
const selectedIds = Array.from(checkboxes).filter(c => c.checked).map(c => c.value);
document.getElementById(hiddenInputId).value = JSON.stringify(selectedIds);
});
}
setupBulkModal('bulkStatusModal', 'bulkStatusPersonIds');
setupBulkModal('bulkEventModal', 'bulkEventPersonIds');
setupBulkModal('bulkInitModal', 'bulkInitPersonIds');
const printBadgeBtn = document.getElementById('bulkPrintBadge');
if(printBadgeBtn) {
printBadgeBtn.addEventListener('click', function(e) {
e.preventDefault();
const selectedIds = Array.from(checkboxes).filter(c => c.checked).map(c => c.value);
if (selectedIds.length === 0) {
alert('Proszę zaznaczyć przynajmniej jedną osobę.');
return;
}
// Create a form to POST the data
const form = document.createElement('form');
form.method = 'post';
form.action = '_bulk_print_badges.php';
form.target = '_blank'; // Open in a new tab
const hiddenInput = document.createElement('input');
hiddenInput.type = 'hidden';
hiddenInput.name = 'person_ids';
hiddenInput.value = JSON.stringify(selectedIds);
form.appendChild(hiddenInput);
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
});
}
const printAttendanceBtn = document.getElementById('bulkPrintAttendance');
if(printAttendanceBtn) {
printAttendanceBtn.addEventListener('click', function(e) {
e.preventDefault();
const selectedIds = Array.from(checkboxes).filter(c => c.checked).map(c => c.value);
if (selectedIds.length === 0) {
alert('Proszę zaznaczyć przynajmniej jedną osobę.');
return;
}
const form = document.createElement('form');
form.method = 'post';
form.action = '_bulk_print_attendance_list.php';
form.target = '_blank';
const hiddenInput = document.createElement('input');
hiddenInput.type = 'hidden';
hiddenInput.name = 'person_ids';
hiddenInput.value = JSON.stringify(selectedIds);
form.appendChild(hiddenInput);
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
});
}
// Populate edit person modal
const editPersonModal = document.getElementById('editPersonModal');
if(editPersonModal) {
editPersonModal.addEventListener('show.bs.modal', function (event) {
const button = event.relatedTarget;
const personId = button.getAttribute('data-person-id');
var personName = button.getAttribute('data-person-name');
var deleteBtn = document.getElementById('deleteUserBtn');
deleteBtn.dataset.personId = personId;
deleteBtn.dataset.personName = personName;
fetch('_get_person_details.php?id=' + personId)
.then(response => response.json())
.then(data => {
document.getElementById('editPersonId').value = data.person.id;
document.getElementById('editFirstName').value = data.person.first_name;
document.getElementById('editLastName').value = data.person.last_name;
document.getElementById('editEmail').value = data.person.email;
document.getElementById('editCompanyName').value = data.person.company_name;
document.getElementById('editPhone').value = data.person.phone;
document.getElementById('editRole').value = data.person.role;
document.getElementById('editBniGroup').value = data.person.bni_group_id || '';
document.getElementById('editNip').value = data.person.nip || '';
document.getElementById('editIndustry').value = data.person.industry || '';
document.getElementById('editCompanySize').value = data.person.company_size_revenue || '';
document.getElementById('editBusinessDescription').value = data.person.business_description || '';
document.getElementById('editCompanyLogoPath').textContent = data.person.company_logo_path || '';
document.getElementById('editPersonPhotoPath').textContent = data.person.person_photo_path || '';
document.getElementById('editGainsSheetPath').textContent = data.person.gains_sheet_path || '';
document.getElementById('editTopWantedPath').textContent = data.person.top_wanted_contacts_path || '';
document.getElementById('editTopOwnedPath').textContent = data.person.top_owned_contacts_path || '';
// Trigger change to show/hide group div and member-only fields
const editRoleSelect = document.getElementById('editRole');
editRoleSelect.dispatchEvent(new Event('change'));
const functionsSelect = document.getElementById('editRoles');
functionsSelect.innerHTML = ''; // Clear existing options
// Group functions by group_name
const groupedFunctions = data.all_functions.reduce((acc, func) => {
const groupName = func.group_name || 'Other';
if (!acc[groupName]) {
acc[groupName] = [];
}
acc[groupName].push(func);
return acc;
}, {});
// Populate select with optgroups
for (const groupName in groupedFunctions) {
const optgroup = document.createElement('optgroup');
optgroup.label = groupName;
groupedFunctions[groupName].forEach(func => {
const option = document.createElement('option');
option.value = func.id;
option.textContent = func.name;
if (data.person_functions.map(String).includes(String(func.id))) {
option.selected = true;
}
optgroup.appendChild(option);
});
functionsSelect.appendChild(optgroup);
}
});
});
}
// When the delete button in the edit modal is clicked, pass the data to the delete confirmation modal
document.getElementById('deleteUserBtn').addEventListener('click', function() {
var personId = this.dataset.personId;
var personName = this.dataset.personName;
var deletePersonModal = document.getElementById('deletePersonModal');
deletePersonModal.querySelector('#personNameToDelete').textContent = personName;
deletePersonModal.dataset.personId = personId;
});
// Populate delete person modal
var deletePersonModal = document.getElementById('deletePersonModal');
deletePersonModal.addEventListener('show.bs.modal', function (event) {
var button = event.relatedTarget;
if (button.id !== 'deleteUserBtn') {
var personId = button.dataset.personId;
var personName = button.dataset.personName;
document.getElementById('personNameToDelete').textContent = personName;
deletePersonModal.dataset.personId = personId;
}
});
document.getElementById('confirmDeleteBtn').addEventListener('click', function() {
let personIdToDelete = deletePersonModal.dataset.personId;
if (personIdToDelete) {
const formData = new FormData();
formData.append('person_id', personIdToDelete);
fetch('_delete_person.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
const modal = bootstrap.Modal.getInstance(deletePersonModal);
modal.hide();
if (data.success) {
window.location.reload();
} else {
let errorAlert = document.querySelector('.alert-danger');
let errorContainer = errorAlert.parentElement;
if (!errorAlert) {
errorContainer = document.querySelector('main'); // fallback
const alertHTML = `
<div class="alert alert-danger alert-dismissible fade show mt-3" role="alert">
${data.error}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>`;
errorContainer.insertAdjacentHTML('afterbegin', alertHTML);
} else {
errorAlert.innerHTML = `${data.error} <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>`;
errorAlert.classList.remove('d-none');
}
}
})
.catch(error => {
console.error('Error:', error);
const modal = bootstrap.Modal.getInstance(deletePersonModal);
modal.hide();
});
}
});
// Handle role change for group visibility
const createRoleSelect = document.getElementById('createRole');
const createGroupDiv = document.getElementById('create-group-selection-div');
const createMemberOnlyFields = document.querySelector('#createPersonModal .member-only-fields');
createRoleSelect.addEventListener('change', function() {
const isMember = this.value === 'member';
createGroupDiv.style.display = isMember ? 'block' : 'none';
createMemberOnlyFields.style.display = isMember ? 'block' : 'none';
});
// Initial check
const isMemberCreate = createRoleSelect.value === 'member';
createGroupDiv.style.display = isMemberCreate ? 'block' : 'none';
createMemberOnlyFields.style.display = isMemberCreate ? 'block' : 'none';
const editRoleSelect = document.getElementById('editRole');
const editGroupDiv = document.getElementById('edit-group-selection-div');
const editMemberOnlyFields = document.querySelector('#editPersonModal .member-only-fields');
editRoleSelect.addEventListener('change', function() {
const isMember = this.value === 'member';
editGroupDiv.style.display = isMember ? 'block' : 'none';
editMemberOnlyFields.style.display = isMember ? 'block' : 'none';
});
});
</script>
<!-- Bulk Modals -->
<!-- Bulk Status Update Modal -->
<div class="modal fade" id="bulkStatusModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><?= t('dashboard.bulk_status_update', 'Zbiorcza aktualizacja statusu') ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form action="_bulk_update_status.php" method="post">
<input type="hidden" name="person_ids" id="bulkStatusPersonIds">
<div class="mb-3">
<label class="form-label"><?= t('form.process', 'Proces') ?></label>
<select name="process_id" class="form-select" required>
<?php foreach($processes as $process): ?>
<option value="<?= $process['id'] ?>"><?= htmlspecialchars($process['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label class="form-label"><?= t('form.new_status', 'Nowy status') ?></label>
<select name="status" class="form-select" required>
<option value="none">None</option>
<option value="negative">Negative</option>
<option value="in_progress">In Progress</option>
<option value="positive">Positive</option>
</select>
</div>
<button type="submit" class="btn btn-primary"><?= t('dashboard.update_status', 'Zaktualizuj status') ?></button>
</form>
</div>
</div>
</div>
</div>
<!-- Bulk Add Event Modal -->
<div class="modal fade" id="bulkEventModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><?= t('dashboard.bulk_add_event', 'Zbiorcze dodawanie zdarzenia') ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form action="_bulk_add_event.php" method="post">
<input type="hidden" name="person_ids" id="bulkEventPersonIds">
<div class="mb-3">
<label class="form-label"><?= t('form.process', 'Proces') ?></label>
<select name="process_id" class="form-select" required>
<?php foreach($processes as $process): ?>
<option value="<?= $process['id'] ?>"><?= htmlspecialchars($process['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label class="form-label"><?= t('form.event_description', 'Opis zdarzenia') ?></label>
<textarea name="description" class="form-control" required></textarea>
</div>
<button type="submit" class="btn btn-primary"><?= t('dashboard.add_event', 'Dodaj zdarzenie') ?></button>
</form>
</div>
</div>
</div>
</div>
<!-- Bulk Initialize Instances Modal -->
<div class="modal fade" id="bulkInitModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><?= t('dashboard.bulk_init_instances', 'Zbiorcza inicjalizacja instancji') ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form action="_bulk_init_instances.php" method="post">
<input type="hidden" name="person_ids" id="bulkInitPersonIds">
<div class="mb-3">
<label class="form-label"><?= t('form.process', 'Proces') ?></label> <select name="process_id" class="form-select" required>
<?php foreach($processes as $process): ?>
<option value="<?= $process['id'] ?>"><?= htmlspecialchars($process['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
<p>This will initialize this process for all selected people if it is not already initialized.</p>
<button type="submit" class="btn btn-primary"><?= t('dashboard.initialize', 'Inicjalizuj') ?></button>
</form>
</div>
</div>
</div>
</div>