feat: redesign tickets main view and basket view with improved styles and layout

- Updated SCSS for tickets main view and basket view, enhancing visual design and responsiveness.
- Added new calendar functionality in the admin panel for managing ticket availability.
- Implemented error handling for ticket availability in the basket view.
- Introduced a new calendar availability table in the database for tracking ticket dates.
- Added a new link to the calendar in the logged-in user navigation.
- Improved ticket selection logic to disable unavailable tickets in the main view.
- Created guidelines for code standards in AGENTS.md.
This commit is contained in:
2026-03-06 01:06:43 +01:00
parent 238c9ecaed
commit 38f5babde3
14 changed files with 2218 additions and 261 deletions

View File

@@ -276,4 +276,67 @@ class Apanel
echo json_encode(['status' => 'ok']);
exit;
}
}
static public function calendar()
{
$token = bin2hex(random_bytes(32));
\S::set_session('admin_calendar_csrf', $token);
return \Tpl::view('admin-panel/calendar', [
'calendar_groups' => \factory\Tickets::getCalendarDefinitions(),
'csrf_token' => $token
]);
}
static public function calendar_dates()
{
header('Content-Type: application/json; charset=utf-8');
$groupKey = trim((string) \S::get('ticket_group'));
$definitions = \factory\Tickets::getCalendarDefinitions();
if (!isset($definitions[$groupKey])) {
echo json_encode(['status' => 'error', 'message' => 'Niepoprawny rodzaj biletu.']);
exit;
}
$dates = \factory\Tickets::getEnabledDatesByGroup($groupKey);
echo json_encode([
'status' => 'ok',
'enabled_dates' => $dates
]);
exit;
}
static public function calendar_save()
{
header('Content-Type: application/json; charset=utf-8');
$sessionToken = (string) \S::get_session('admin_calendar_csrf');
$requestToken = trim((string) \S::get('csrf_token'));
if (empty($sessionToken) || empty($requestToken) || !hash_equals($sessionToken, $requestToken)) {
echo json_encode(['status' => 'error', 'message' => 'Niepoprawny token CSRF.']);
exit;
}
$groupKey = trim((string) \S::get('ticket_group'));
$definitions = \factory\Tickets::getCalendarDefinitions();
if (!isset($definitions[$groupKey])) {
echo json_encode(['status' => 'error', 'message' => 'Niepoprawny rodzaj biletu.']);
exit;
}
$dates = $_POST['dates'] ?? [];
if (!is_array($dates)) {
$dates = [];
}
$saved = \factory\Tickets::saveEnabledDatesForGroup($groupKey, $dates);
if (!$saved) {
echo json_encode(['status' => 'error', 'message' => 'Nie udało się zapisać kalendarza.']);
exit;
}
echo json_encode(['status' => 'ok']);
exit;
}
}

View File

@@ -9,13 +9,24 @@ class Tickets
global $settings;
$enable_sell = \factory\Apanel::getSetting('enable_sell', '1');
$selectedDate = \S::get('selected_date');
$normalizedSelectedDate = \factory\Tickets::normalizeDateFromPicker($selectedDate);
$ticketAvailability = [];
if ($normalizedSelectedDate) {
$ticketAvailability = \factory\Tickets::getTicketAvailabilityForDate(
array_keys($settings['tickets']),
$normalizedSelectedDate
);
}
if ( !$enable_sell || $enable_sell === '0' )
return \Tpl::view( 'tickets/disabled-sell' );
return \Tpl::view('tickets/main-view', [
'cart' => \S::get_session('basket'),
'settings' => $settings
'settings' => $settings,
'ticket_availability' => $ticketAvailability
]);
}
@@ -23,19 +34,45 @@ class Tickets
{
global $settings;
$selected_date = \S::get( 'date' ) ? \S::get( 'date' ) : null;
$diffDays = \S::get('diffdays') ?? 0;
$ticket_id = \S::get('ticket_id');
$basket = \S::get_session('basket');
if (!$selected_date && isset($basket[$ticket_id][$diffDays]['date'])) {
$selected_date = $basket[$ticket_id][$diffDays]['date'];
}
if (!$selected_date && \factory\Tickets::getCalendarGroupForTicket($ticket_id)) {
echo json_encode([
'status' => 'error',
'message' => 'Wybierz datę wizyty dla tego biletu.'
]);
exit;
}
if ( $selected_date )
{
$selected = new \DateTime($selected_date);
$selected = \DateTime::createFromFormat('d-m-Y', $selected_date);
if (!$selected) {
echo json_encode([
'status' => 'error',
'message' => 'Niepoprawna data wizyty.'
]);
exit;
}
$today = new \DateTime(date('Y-m-d') . ' 00:00:00');
$diffDays = $selected->diff($today)->days;
}
$basket = \S::get_session('basket');
$ticket_id = \S::get('ticket_id');
if (!\factory\Tickets::canBuyTicketOnDate($ticket_id, $selected_date)) {
echo json_encode([
'status' => 'error',
'message' => 'Ten rodzaj biletu jest niedostępny w wybranym dniu.'
]);
exit;
}
}
if ( !empty($basket[$ticket_id][$diffDays]) )
{
@@ -53,7 +90,8 @@ class Tickets
$addon = 0;
}
$is_weekend = $selected_date && in_array((new \DateTime($selected_date))->format('N'), ['6', '7']);
$selectedDateObject = $selected_date ? \DateTime::createFromFormat('d-m-Y', $selected_date) : null;
$is_weekend = $selectedDateObject && in_array($selectedDateObject->format('N'), ['6', '7']);
$base_price = $is_weekend
? ($settings['tickets'][$ticket_id]['price_weekend'] ?? $settings['tickets'][$ticket_id]['price'])
: $settings['tickets'][$ticket_id]['price'];
@@ -228,6 +266,24 @@ class Tickets
global $settings, $mdb;
$basket = \S::get_session('basket');
if (empty($basket) || !is_array($basket)) {
header('Location: /tickets/main_view/');
exit;
}
foreach ($basket as $ticketId => $variants) {
foreach ($variants as $variant) {
if (empty($variant['date'])) {
continue;
}
if (!\factory\Tickets::canBuyTicketOnDate($ticketId, $variant['date'])) {
header('Location: /tickets/basket_view/?calendar_error=1');
exit;
}
}
}
$date = date('Y-m-d H:i:s');
$finalPrice = 0;
@@ -637,4 +693,4 @@ class Tickets
{
return \Tpl::view('site/regulamin-for-gifts');
}
}
}