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:
@@ -115,3 +115,10 @@ initial_prompt: ""
|
|||||||
# override of the corresponding setting in serena_config.yml, see the documentation there.
|
# override of the corresponding setting in serena_config.yml, see the documentation there.
|
||||||
# If null or missing, the value from the global config is used.
|
# If null or missing, the value from the global config is used.
|
||||||
symbol_info_budget:
|
symbol_info_budget:
|
||||||
|
|
||||||
|
# The language backend to use for this project.
|
||||||
|
# If not set, the global setting from serena_config.yml is used.
|
||||||
|
# Valid values: LSP, JetBrains
|
||||||
|
# Note: the backend is fixed at startup. If a project with a different backend
|
||||||
|
# is activated post-init, an error will be returned.
|
||||||
|
language_backend:
|
||||||
|
|||||||
1018
.vscode/ftp-kr.sync.cache.json
vendored
1018
.vscode/ftp-kr.sync.cache.json
vendored
File diff suppressed because it is too large
Load Diff
14
AGENTS.md
Normal file
14
AGENTS.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# Zasady pisania kodu
|
||||||
|
- Kod ma być czytelny „dla obcego”: jasne nazwy, mało magii
|
||||||
|
- Brak „skrótów na szybko” typu logika w widokach, copy-paste, losowe helpery bez spójności
|
||||||
|
- Każda funkcja/klasa ma mieć jedną odpowiedzialność, zwykle do 30–50 linii (jeśli dłuższe – dzielić)
|
||||||
|
- max 3 poziomy zagnieżdżeń (if/foreach), reszta do osobnych metod
|
||||||
|
- Nazewnictwo:
|
||||||
|
- klasy: PascalCase
|
||||||
|
- metody/zmienne: camelCase
|
||||||
|
- stałe: UPPER_SNAKE_CASE
|
||||||
|
- Zero „skrótologii” w nazwach (np. $d, $tmp, $x1) poza pętlami 2–3 linijki
|
||||||
|
- medoo + prepared statements bez wyjątków (żadnego sklejania SQL stringiem)
|
||||||
|
- XSS: escape w widokach (np. helper e())
|
||||||
|
- CSRF dla formularzy, sensowna obsługa sesji
|
||||||
|
- Kod ma mieć komentarze tylko tam, gdzie wyjaśniają „dlaczego”, nie „co”
|
||||||
@@ -276,4 +276,67 @@ class Apanel
|
|||||||
echo json_encode(['status' => 'ok']);
|
echo json_encode(['status' => 'ok']);
|
||||||
exit;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,13 +9,24 @@ class Tickets
|
|||||||
global $settings;
|
global $settings;
|
||||||
|
|
||||||
$enable_sell = \factory\Apanel::getSetting('enable_sell', '1');
|
$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' )
|
if ( !$enable_sell || $enable_sell === '0' )
|
||||||
return \Tpl::view( 'tickets/disabled-sell' );
|
return \Tpl::view( 'tickets/disabled-sell' );
|
||||||
|
|
||||||
return \Tpl::view('tickets/main-view', [
|
return \Tpl::view('tickets/main-view', [
|
||||||
'cart' => \S::get_session('basket'),
|
'cart' => \S::get_session('basket'),
|
||||||
'settings' => $settings
|
'settings' => $settings,
|
||||||
|
'ticket_availability' => $ticketAvailability
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,19 +34,45 @@ class Tickets
|
|||||||
{
|
{
|
||||||
global $settings;
|
global $settings;
|
||||||
|
|
||||||
|
|
||||||
$selected_date = \S::get( 'date' ) ? \S::get( 'date' ) : null;
|
$selected_date = \S::get( 'date' ) ? \S::get( 'date' ) : null;
|
||||||
$diffDays = \S::get('diffdays') ?? 0;
|
$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 )
|
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');
|
$today = new \DateTime(date('Y-m-d') . ' 00:00:00');
|
||||||
$diffDays = $selected->diff($today)->days;
|
$diffDays = $selected->diff($today)->days;
|
||||||
}
|
|
||||||
|
|
||||||
$basket = \S::get_session('basket');
|
if (!\factory\Tickets::canBuyTicketOnDate($ticket_id, $selected_date)) {
|
||||||
$ticket_id = \S::get('ticket_id');
|
echo json_encode([
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'Ten rodzaj biletu jest niedostępny w wybranym dniu.'
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( !empty($basket[$ticket_id][$diffDays]) )
|
if ( !empty($basket[$ticket_id][$diffDays]) )
|
||||||
{
|
{
|
||||||
@@ -53,7 +90,8 @@ class Tickets
|
|||||||
$addon = 0;
|
$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
|
$base_price = $is_weekend
|
||||||
? ($settings['tickets'][$ticket_id]['price_weekend'] ?? $settings['tickets'][$ticket_id]['price'])
|
? ($settings['tickets'][$ticket_id]['price_weekend'] ?? $settings['tickets'][$ticket_id]['price'])
|
||||||
: $settings['tickets'][$ticket_id]['price'];
|
: $settings['tickets'][$ticket_id]['price'];
|
||||||
@@ -228,6 +266,24 @@ class Tickets
|
|||||||
global $settings, $mdb;
|
global $settings, $mdb;
|
||||||
|
|
||||||
$basket = \S::get_session('basket');
|
$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');
|
$date = date('Y-m-d H:i:s');
|
||||||
|
|
||||||
$finalPrice = 0;
|
$finalPrice = 0;
|
||||||
@@ -637,4 +693,4 @@ class Tickets
|
|||||||
{
|
{
|
||||||
return \Tpl::view('site/regulamin-for-gifts');
|
return \Tpl::view('site/regulamin-for-gifts');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,203 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace factory;
|
namespace factory;
|
||||||
class Tickets {
|
class Tickets {
|
||||||
|
private static $calendarTableReady = false;
|
||||||
|
private static $allowedDateCache = [];
|
||||||
|
|
||||||
|
static public function getCalendarDefinitions()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'park-rozrywki' => [
|
||||||
|
'label' => 'Park rozrywki i dinozaurów + bilety prezentowe',
|
||||||
|
'ticket_ids' => [
|
||||||
|
'plac-zabaw-ulgowy',
|
||||||
|
'plac-zabaw-normalny',
|
||||||
|
'gift-plac-zabaw-ulgowy',
|
||||||
|
'gift-plac-zabaw-normalny',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'park-wodny' => [
|
||||||
|
'label' => 'Park wodny',
|
||||||
|
'ticket_ids' => [
|
||||||
|
'park-wodny-ulgowy',
|
||||||
|
'park-wodny-normalny',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'all-open' => [
|
||||||
|
'label' => 'All Open + bilety prezentowe',
|
||||||
|
'ticket_ids' => [
|
||||||
|
'bilet-all-open-ulgowy',
|
||||||
|
'bilet-all-open-normalny',
|
||||||
|
'gift-bilet-all-open-ulgowy',
|
||||||
|
'gift-bilet-all-open-normalny',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function ensureCalendarTable()
|
||||||
|
{
|
||||||
|
global $mdb;
|
||||||
|
|
||||||
|
if (self::$calendarTableReady) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql = "CREATE TABLE IF NOT EXISTS ticket_calendar_availability (
|
||||||
|
ticket_group VARCHAR(64) NOT NULL,
|
||||||
|
available_date DATE NOT NULL,
|
||||||
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (ticket_group, available_date)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8";
|
||||||
|
|
||||||
|
$mdb->pdo->exec($sql);
|
||||||
|
self::$calendarTableReady = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function normalizeDateFromPicker($date)
|
||||||
|
{
|
||||||
|
$date = trim((string) $date);
|
||||||
|
if ($date === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$formats = ['d-m-Y', 'Y-m-d'];
|
||||||
|
foreach ($formats as $format) {
|
||||||
|
$parsedDate = \DateTime::createFromFormat($format, $date);
|
||||||
|
if ($parsedDate && $parsedDate->format($format) === $date) {
|
||||||
|
return $parsedDate->format('Y-m-d');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function getCalendarGroupForTicket($ticketId)
|
||||||
|
{
|
||||||
|
foreach (self::getCalendarDefinitions() as $groupKey => $group) {
|
||||||
|
if (in_array($ticketId, $group['ticket_ids'], true)) {
|
||||||
|
return $groupKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function getEnabledDatesByGroup($groupKey)
|
||||||
|
{
|
||||||
|
global $mdb;
|
||||||
|
|
||||||
|
self::ensureCalendarTable();
|
||||||
|
$definitions = self::getCalendarDefinitions();
|
||||||
|
|
||||||
|
if (!isset($definitions[$groupKey])) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$statement = $mdb->pdo->prepare(
|
||||||
|
"SELECT available_date
|
||||||
|
FROM ticket_calendar_availability
|
||||||
|
WHERE ticket_group = :ticket_group
|
||||||
|
ORDER BY available_date ASC"
|
||||||
|
);
|
||||||
|
$statement->execute([':ticket_group' => $groupKey]);
|
||||||
|
|
||||||
|
$rows = $statement->fetchAll(\PDO::FETCH_ASSOC);
|
||||||
|
if (!is_array($rows)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_values(array_filter(array_map(static function ($row) {
|
||||||
|
return $row['available_date'] ?? null;
|
||||||
|
}, $rows)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function saveEnabledDatesForGroup($groupKey, array $dates)
|
||||||
|
{
|
||||||
|
global $mdb;
|
||||||
|
|
||||||
|
self::ensureCalendarTable();
|
||||||
|
$definitions = self::getCalendarDefinitions();
|
||||||
|
|
||||||
|
if (!isset($definitions[$groupKey])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$normalizedDates = [];
|
||||||
|
foreach ($dates as $date) {
|
||||||
|
$normalizedDate = self::normalizeDateFromPicker($date);
|
||||||
|
if (!$normalizedDate) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$normalizedDates[$normalizedDate] = $normalizedDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
$normalizedDates = array_values($normalizedDates);
|
||||||
|
|
||||||
|
$mdb->pdo->beginTransaction();
|
||||||
|
try {
|
||||||
|
$deleteStatement = $mdb->pdo->prepare(
|
||||||
|
"DELETE FROM ticket_calendar_availability WHERE ticket_group = :ticket_group"
|
||||||
|
);
|
||||||
|
$deleteStatement->execute([':ticket_group' => $groupKey]);
|
||||||
|
|
||||||
|
if (!empty($normalizedDates)) {
|
||||||
|
$insertStatement = $mdb->pdo->prepare(
|
||||||
|
"INSERT INTO ticket_calendar_availability (ticket_group, available_date)
|
||||||
|
VALUES (:ticket_group, :available_date)"
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($normalizedDates as $date) {
|
||||||
|
$insertStatement->execute([
|
||||||
|
':ticket_group' => $groupKey,
|
||||||
|
':available_date' => $date,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$mdb->pdo->commit();
|
||||||
|
} catch (\Exception $exception) {
|
||||||
|
$mdb->pdo->rollBack();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$allowedDateCache = [];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function canBuyTicketOnDate($ticketId, $date)
|
||||||
|
{
|
||||||
|
$groupKey = self::getCalendarGroupForTicket($ticketId);
|
||||||
|
if (!$groupKey) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$normalizedDate = self::normalizeDateFromPicker($date);
|
||||||
|
if (!$normalizedDate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cacheKey = $groupKey . '|' . $normalizedDate;
|
||||||
|
if (array_key_exists($cacheKey, self::$allowedDateCache)) {
|
||||||
|
return self::$allowedDateCache[$cacheKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
$enabledDates = self::getEnabledDatesByGroup($groupKey);
|
||||||
|
$isAllowed = in_array($normalizedDate, $enabledDates, true);
|
||||||
|
self::$allowedDateCache[$cacheKey] = $isAllowed;
|
||||||
|
|
||||||
|
return $isAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function getTicketAvailabilityForDate(array $ticketIds, $date)
|
||||||
|
{
|
||||||
|
$availability = [];
|
||||||
|
foreach ($ticketIds as $ticketId) {
|
||||||
|
$availability[$ticketId] = self::canBuyTicketOnDate($ticketId, $date);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $availability;
|
||||||
|
}
|
||||||
|
|
||||||
static public function recalculate_ticket_protection( $basket ) {
|
static public function recalculate_ticket_protection( $basket ) {
|
||||||
global $settings;
|
global $settings;
|
||||||
@@ -110,4 +307,4 @@ class Tickets {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
layout/.DS_Store
vendored
BIN
layout/.DS_Store
vendored
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -1453,4 +1453,729 @@ body {
|
|||||||
75% {
|
75% {
|
||||||
transform: translateX(-2px);
|
transform: translateX(-2px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Tickets main view redesign */
|
||||||
|
#tickets-main-view {
|
||||||
|
.tickets_calendar {
|
||||||
|
margin-top: 48px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dateForm {
|
||||||
|
max-width: 1040px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background: linear-gradient(160deg, #ffffff 0%, #f6faef 100%);
|
||||||
|
border: 1px solid rgba(114, 184, 27, 0.2);
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 26px 24px;
|
||||||
|
box-shadow: 0 12px 28px rgba(36, 58, 11, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
#dateForm ._title {
|
||||||
|
width: 100%;
|
||||||
|
text-align: left;
|
||||||
|
font-size: 30px;
|
||||||
|
line-height: 1.15;
|
||||||
|
font-weight: 900;
|
||||||
|
letter-spacing: 0.2px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flatpickr-calendar.inline {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 420px;
|
||||||
|
margin: 0 auto;
|
||||||
|
border-radius: 16px;
|
||||||
|
box-shadow: 0 8px 22px rgba(51, 51, 51, 0.08);
|
||||||
|
border: 1px solid #e8eed6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets {
|
||||||
|
width: min(1120px, calc(100% - 30px));
|
||||||
|
margin: 0 auto 60px;
|
||||||
|
gap: 42px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket-container {
|
||||||
|
gap: 18px;
|
||||||
|
align-items: stretch;
|
||||||
|
background: rgba(255, 255, 255, 0.72);
|
||||||
|
border: 1px solid rgba(51, 51, 51, 0.08);
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 26px 22px 18px;
|
||||||
|
box-shadow: 0 8px 26px rgba(21, 39, 5, 0.05);
|
||||||
|
backdrop-filter: blur(2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket-container .title-container {
|
||||||
|
padding-bottom: 14px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket-container .title-container::after {
|
||||||
|
width: 140px;
|
||||||
|
border-bottom: 2px dashed rgba(51, 51, 51, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket-container .title-container .title {
|
||||||
|
font-size: clamp(30px, 4vw, 44px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket-container .title-container .description {
|
||||||
|
font-size: clamp(14px, 2.5vw, 20px);
|
||||||
|
line-height: 1.3;
|
||||||
|
margin-bottom: 0;
|
||||||
|
color: #4f5d48;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket {
|
||||||
|
width: 100%;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr) auto auto;
|
||||||
|
gap: 16px 20px;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 16px;
|
||||||
|
background: #ffffff;
|
||||||
|
border: 1px solid #edf1e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-description {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 86px;
|
||||||
|
padding: 16px 14px;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-description .ticket__name {
|
||||||
|
font-size: clamp(22px, 3.2vw, 31px);
|
||||||
|
line-height: 1.05;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-description .description {
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-description .ticket-alert {
|
||||||
|
font-size: 13px;
|
||||||
|
margin-top: 10px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .price {
|
||||||
|
margin-left: 0;
|
||||||
|
min-width: 105px;
|
||||||
|
text-align: right;
|
||||||
|
font-size: clamp(31px, 3.5vw, 40px);
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-quantity {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-quantity .button {
|
||||||
|
border-radius: 999px;
|
||||||
|
padding: 11px 16px;
|
||||||
|
min-width: 170px;
|
||||||
|
font-size: 13px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.35px;
|
||||||
|
box-shadow: 0 6px 14px rgba(114, 184, 27, 0.22);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-quantity .button:disabled {
|
||||||
|
background: #d6dccd;
|
||||||
|
color: #5d6658;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-info__description {
|
||||||
|
max-width: 1120px;
|
||||||
|
margin: 0 auto;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include respond-below(md) {
|
||||||
|
#dateForm ._title {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket {
|
||||||
|
grid-template-columns: 1fr auto;
|
||||||
|
grid-template-areas:
|
||||||
|
"desc desc"
|
||||||
|
"price button";
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-description {
|
||||||
|
grid-area: desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .price {
|
||||||
|
grid-area: price;
|
||||||
|
text-align: left;
|
||||||
|
min-width: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-quantity {
|
||||||
|
grid-area: button;
|
||||||
|
justify-self: end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include respond-below(sm) {
|
||||||
|
.tickets_calendar {
|
||||||
|
margin-top: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dateForm {
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 18px 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets {
|
||||||
|
width: calc(100% - 20px);
|
||||||
|
gap: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket-container {
|
||||||
|
border-radius: 14px;
|
||||||
|
padding: 16px 10px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket {
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-description {
|
||||||
|
min-height: 76px;
|
||||||
|
padding: 12px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-quantity .button {
|
||||||
|
min-width: 132px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Basket view redesign */
|
||||||
|
#basket_page {
|
||||||
|
.basket_content {
|
||||||
|
width: min(1120px, calc(100% - 30px));
|
||||||
|
margin: 42px auto 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_01 table {
|
||||||
|
border-radius: 16px;
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid #dfe8cd;
|
||||||
|
box-shadow: 0 10px 26px rgba(30, 43, 18, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_01 table tr th {
|
||||||
|
background: #f4f9ea;
|
||||||
|
border-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_01 table tr th h3 {
|
||||||
|
font-size: 1rem;
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_01 table tr td {
|
||||||
|
font-size: 15px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_01 table tr td .ticket-date {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 4px;
|
||||||
|
padding: 3px 8px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #f2f7e8;
|
||||||
|
color: #5a6650;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_01 table tr td .btn_t1 {
|
||||||
|
background: #f6faef;
|
||||||
|
border: 1px solid #dce8c5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_01 .basket_protection {
|
||||||
|
margin-top: 12px;
|
||||||
|
background: #f7fbe9;
|
||||||
|
border: 1px solid #dce8c5;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_01 .basket_protection .ticket_protection {
|
||||||
|
color: #4f6f1f;
|
||||||
|
font-weight: 700;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_01 .basket_protection .ticket_protection:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_01 .basket_protection__text p {
|
||||||
|
color: #5a6650;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_user_data .basket_user_data__wrapper {
|
||||||
|
border-radius: 16px;
|
||||||
|
border: 1px solid #dfe8cd;
|
||||||
|
box-shadow: 0 10px 26px rgba(30, 43, 18, 0.08);
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_user_data .basket_user_data__wrapper h2 {
|
||||||
|
font-weight: 900;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_user_data .basket_user_data__wrapper .form-control {
|
||||||
|
border-radius: 10px;
|
||||||
|
border-color: #d6dfc6;
|
||||||
|
min-height: 42px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_user_data .basket_user_data__wrapper .form-control:focus {
|
||||||
|
border-color: #72b81b;
|
||||||
|
box-shadow: 0 0 0 0.2rem rgba(114, 184, 27, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_summary .basket_summary__wrapper {
|
||||||
|
border-radius: 16px;
|
||||||
|
border: 1px solid #dfe8cd;
|
||||||
|
box-shadow: 0 10px 26px rgba(30, 43, 18, 0.08);
|
||||||
|
background: linear-gradient(165deg, #ffffff 0%, #f5faea 100%);
|
||||||
|
padding: 28px 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_summary .basket_summary__wrapper h2 {
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_summary .basket_summary__wrapper p {
|
||||||
|
font-size: 2rem;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_summary .basket_summary__wrapper .buy-btn {
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #72b81b;
|
||||||
|
color: #fff;
|
||||||
|
min-width: 150px;
|
||||||
|
padding: 10px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_summary .basket_summary__wrapper .buy-btn:hover {
|
||||||
|
background: #5e9c15;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include respond-below(md) {
|
||||||
|
.basket_content {
|
||||||
|
width: calc(100% - 20px);
|
||||||
|
margin-top: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_user_data .basket_user_data__wrapper,
|
||||||
|
.box_02 .basket_summary .basket_summary__wrapper {
|
||||||
|
padding: 16px 12px;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include respond-below(sm) {
|
||||||
|
.basket_content {
|
||||||
|
margin-top: 14px;
|
||||||
|
margin-bottom: 26px;
|
||||||
|
width: calc(100% - 14px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_01 {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_01 table tr {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_01 table td {
|
||||||
|
min-height: 34px;
|
||||||
|
padding-top: 6px !important;
|
||||||
|
padding-bottom: 6px !important;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_01 table tr td .btn_t1 {
|
||||||
|
width: 26px;
|
||||||
|
height: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_01 .basket_protection {
|
||||||
|
margin-top: 8px;
|
||||||
|
padding: 8px 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_01 .basket_protection .ticket_protection {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_01 .basket_protection__text p {
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.35;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_user_data .basket_user_data__wrapper {
|
||||||
|
padding: 12px 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_user_data .basket_user_data__wrapper h2 {
|
||||||
|
font-size: 1.15rem;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_user_data .basket_user_data__wrapper .form-group {
|
||||||
|
margin-bottom: 0.35rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_user_data .basket_user_data__wrapper .form-control {
|
||||||
|
min-height: 36px;
|
||||||
|
font-size: 14px;
|
||||||
|
padding-top: 6px;
|
||||||
|
padding-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_user_data .basket_user_data__wrapper .col-form-label,
|
||||||
|
.box_02 .basket_user_data .basket_user_data__wrapper .form-check-label {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_user_data .basket_user_data__wrapper textarea.form-control {
|
||||||
|
min-height: 74px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_summary .basket_summary__wrapper {
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 14px 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_summary .basket_summary__wrapper h2 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_summary .basket_summary__wrapper p {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box_02 .basket_summary .basket_summary__wrapper .buy-btn {
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
padding: 9px 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tickets main view final fixes */
|
||||||
|
#tickets-main-view {
|
||||||
|
--tickets-main-width: min(1120px, calc(100% - 30px));
|
||||||
|
|
||||||
|
.tickets_calendar {
|
||||||
|
width: var(--tickets-main-width);
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dateForm {
|
||||||
|
width: 100%;
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets {
|
||||||
|
width: var(--tickets-main-width);
|
||||||
|
}
|
||||||
|
|
||||||
|
.shopping-cart-container--active .shopping-cart {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.shopping-cart {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(120%);
|
||||||
|
}
|
||||||
|
|
||||||
|
@include respond-below(sm) {
|
||||||
|
--tickets-main-width: calc(100% - 20px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tickets main view refinements */
|
||||||
|
#tickets-main-view {
|
||||||
|
#dateForm {
|
||||||
|
max-width: none;
|
||||||
|
width: min(1120px, calc(100% - 30px));
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .price {
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
padding: 0;
|
||||||
|
min-width: 78px;
|
||||||
|
color: #2b3721;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shopping-cart {
|
||||||
|
width: 320px;
|
||||||
|
right: 18px;
|
||||||
|
top: 84px;
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 12px;
|
||||||
|
gap: 10px;
|
||||||
|
color: #24311c;
|
||||||
|
background: rgba(255, 255, 255, 0.98);
|
||||||
|
border: 1px solid #dfe9cf;
|
||||||
|
box-shadow: 0 18px 34px rgba(28, 43, 14, 0.22);
|
||||||
|
transform: translateX(120%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.shopping-cart .basket {
|
||||||
|
font-size: 22px;
|
||||||
|
color: #72b81b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shopping-cart .quantity {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 900;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shopping-cart .tickets__list {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
max-height: 44svh;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shopping-cart .tickets__list .ticket {
|
||||||
|
margin: 0 0 8px;
|
||||||
|
border: 1px solid #dde6ce;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 8px;
|
||||||
|
font-size: 13px;
|
||||||
|
background: #f9fcf4;
|
||||||
|
grid-template-columns: 1fr 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shopping-cart .tickets__list .ticket__description {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shopping-cart .tickets__list .ticket__price {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #566149;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shopping-cart .tickets__list .ticket .ticket__button {
|
||||||
|
color: #b53b30;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shopping-cart .sum-section {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 8px 10px;
|
||||||
|
background: #f3f8e7;
|
||||||
|
border: 1px solid #dce8c5;
|
||||||
|
font-size: 20px;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shopping-cart .buy-btn {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 11px 14px;
|
||||||
|
background: #72b81b;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shopping-cart .off-btn {
|
||||||
|
top: 8px;
|
||||||
|
right: 10px;
|
||||||
|
color: #72815f;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include respond-below(sm) {
|
||||||
|
#dateForm {
|
||||||
|
width: calc(100% - 20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .price {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shopping-cart {
|
||||||
|
width: calc(100vw - 20px);
|
||||||
|
right: 10px;
|
||||||
|
top: 74px;
|
||||||
|
max-height: calc(100svh - 90px);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tickets cards v2 - more compact, bolder look */
|
||||||
|
#tickets-main-view {
|
||||||
|
.tickets {
|
||||||
|
gap: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket-container {
|
||||||
|
padding: 18px 16px 12px;
|
||||||
|
gap: 12px;
|
||||||
|
border-radius: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket {
|
||||||
|
gap: 12px 14px;
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: 14px;
|
||||||
|
border: 1px solid #e7eddc;
|
||||||
|
box-shadow: 0 6px 16px rgba(25, 33, 19, 0.06);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
inset: auto 0 0 0;
|
||||||
|
height: 2px;
|
||||||
|
background: linear-gradient(90deg, rgba(114, 184, 27, 0.6), rgba(19, 143, 203, 0.2));
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-description {
|
||||||
|
min-height: 64px;
|
||||||
|
padding: 10px 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-description .ticket__name {
|
||||||
|
font-size: clamp(17px, 2.2vw, 23px);
|
||||||
|
line-height: 1.08;
|
||||||
|
letter-spacing: 0.1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-description .description {
|
||||||
|
font-size: 11px;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-description .ticket-alert {
|
||||||
|
margin-top: 6px;
|
||||||
|
font-size: 11px;
|
||||||
|
opacity: 0.95;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .price {
|
||||||
|
font-size: clamp(22px, 2.5vw, 30px);
|
||||||
|
font-weight: 900;
|
||||||
|
min-width: 88px;
|
||||||
|
text-align: center;
|
||||||
|
padding: 8px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #f5f9ed;
|
||||||
|
border: 1px solid #dfeac9;
|
||||||
|
color: #2f3a24;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-quantity .button {
|
||||||
|
min-width: 146px;
|
||||||
|
padding: 9px 12px;
|
||||||
|
font-size: 11px;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include respond-below(md) {
|
||||||
|
.tickets .ticket {
|
||||||
|
grid-template-columns: 1fr auto auto;
|
||||||
|
grid-template-areas: "desc price button";
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-description {
|
||||||
|
grid-area: desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .price {
|
||||||
|
grid-area: price;
|
||||||
|
text-align: center;
|
||||||
|
min-width: 82px;
|
||||||
|
padding: 7px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-quantity {
|
||||||
|
grid-area: button;
|
||||||
|
justify-self: end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include respond-below(sm) {
|
||||||
|
.tickets .ticket {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-areas:
|
||||||
|
"desc"
|
||||||
|
"price"
|
||||||
|
"button";
|
||||||
|
justify-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .price {
|
||||||
|
justify-self: start;
|
||||||
|
font-size: 24px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-quantity {
|
||||||
|
justify-self: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tickets .ticket .ticket-quantity .button {
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
167
templates/admin-panel/calendar.php
Normal file
167
templates/admin-panel/calendar.php
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/flatpickr/dist/l10n/pl.js"></script>
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
|
||||||
|
|
||||||
|
<div id="tickets-calendar-admin">
|
||||||
|
<div class="container">
|
||||||
|
<div class="tickets-orders">
|
||||||
|
<h1>Kalendarz</h1>
|
||||||
|
|
||||||
|
<div class="calendar-controls">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="ticket_group" class="form-label"><strong>Rodzaj biletu</strong></label>
|
||||||
|
<select id="ticket_group" class="form-select">
|
||||||
|
<?php foreach ($this->calendar_groups as $groupKey => $groupData) : ?>
|
||||||
|
<option value="<?= htmlspecialchars($groupKey, ENT_QUOTES, 'UTF-8'); ?>">
|
||||||
|
<?= htmlspecialchars($groupData['label'], ENT_QUOTES, 'UTF-8'); ?>
|
||||||
|
</option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input type="hidden" id="calendar_csrf_token" value="<?= htmlspecialchars($this->csrf_token, ENT_QUOTES, 'UTF-8'); ?>">
|
||||||
|
|
||||||
|
<div id="admin-flatpickr"></div>
|
||||||
|
|
||||||
|
<div class="calendar-buttons mt-3">
|
||||||
|
<button type="button" class="btn btn-outline-success" id="enable-month">Odblokuj cały miesiąc</button>
|
||||||
|
<button type="button" class="btn btn-outline-danger" id="disable-month">Zablokuj cały miesiąc</button>
|
||||||
|
<button type="button" class="btn btn-primary" id="save-calendar">Zapisz</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(function() {
|
||||||
|
let enabledDatesSet = new Set();
|
||||||
|
|
||||||
|
const calendarInstance = flatpickr("#admin-flatpickr", {
|
||||||
|
inline: true,
|
||||||
|
mode: "multiple",
|
||||||
|
dateFormat: "Y-m-d",
|
||||||
|
disableMobile: true,
|
||||||
|
locale: "pl",
|
||||||
|
onChange: function(selectedDates, dateStr, instance) {
|
||||||
|
syncSetWithPicker(instance);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function formatDateToYmd(dateObject) {
|
||||||
|
const year = dateObject.getFullYear();
|
||||||
|
const month = String(dateObject.getMonth() + 1).padStart(2, "0");
|
||||||
|
const day = String(dateObject.getDate()).padStart(2, "0");
|
||||||
|
return year + "-" + month + "-" + day;
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncSetWithPicker(instance) {
|
||||||
|
enabledDatesSet = new Set(instance.selectedDates.map(function(dateObject) {
|
||||||
|
return formatDateToYmd(dateObject);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderCurrentSetToPicker() {
|
||||||
|
calendarInstance.setDate(Array.from(enabledDatesSet), false, "Y-m-d");
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCurrentGroup() {
|
||||||
|
return $('#ticket_group').val();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleError(message) {
|
||||||
|
if ($.alert) {
|
||||||
|
$.alert(message);
|
||||||
|
} else {
|
||||||
|
alert(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchDatesForGroup() {
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
cache: false,
|
||||||
|
url: '/apanel/calendar_dates/',
|
||||||
|
data: {
|
||||||
|
ticket_group: getCurrentGroup()
|
||||||
|
},
|
||||||
|
success: function(rawResponse) {
|
||||||
|
const response = $.parseJSON(rawResponse);
|
||||||
|
if (response.status !== 'ok') {
|
||||||
|
handleError(response.message || 'Nie udało się pobrać danych kalendarza.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
enabledDatesSet = new Set(response.enabled_dates || []);
|
||||||
|
renderCurrentSetToPicker();
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
handleError('Błąd połączenia podczas pobierania kalendarza.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateWholeMonth(enableMonth) {
|
||||||
|
const year = calendarInstance.currentYear;
|
||||||
|
const monthIndex = calendarInstance.currentMonth;
|
||||||
|
const daysInMonth = new Date(year, monthIndex + 1, 0).getDate();
|
||||||
|
|
||||||
|
for (let day = 1; day <= daysInMonth; day++) {
|
||||||
|
const dateObject = new Date(year, monthIndex, day);
|
||||||
|
const dateString = formatDateToYmd(dateObject);
|
||||||
|
if (enableMonth) {
|
||||||
|
enabledDatesSet.add(dateString);
|
||||||
|
} else {
|
||||||
|
enabledDatesSet.delete(dateString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderCurrentSetToPicker();
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveCalendar() {
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
cache: false,
|
||||||
|
url: '/apanel/calendar_save/',
|
||||||
|
data: {
|
||||||
|
ticket_group: getCurrentGroup(),
|
||||||
|
dates: Array.from(enabledDatesSet),
|
||||||
|
csrf_token: $('#calendar_csrf_token').val()
|
||||||
|
},
|
||||||
|
success: function(rawResponse) {
|
||||||
|
const response = $.parseJSON(rawResponse);
|
||||||
|
if (response.status !== 'ok') {
|
||||||
|
handleError(response.message || 'Nie udało się zapisać kalendarza.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($.alert) {
|
||||||
|
$.alert('Kalendarz został zapisany.');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
handleError('Błąd połączenia podczas zapisu kalendarza.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$('body').on('change', '#ticket_group', function() {
|
||||||
|
fetchDatesForGroup();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('body').on('click', '#enable-month', function() {
|
||||||
|
updateWholeMonth(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('body').on('click', '#disable-month', function() {
|
||||||
|
updateWholeMonth(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('body').on('click', '#save-calendar', function() {
|
||||||
|
saveCalendar();
|
||||||
|
});
|
||||||
|
|
||||||
|
fetchDatesForGroup();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -74,6 +74,11 @@
|
|||||||
Cennik
|
Cennik
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="/apanel/calendar/">
|
||||||
|
Kalendarz
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="/apanel/settings/">
|
<a href="/apanel/settings/">
|
||||||
Ustawienia
|
Ustawienia
|
||||||
@@ -139,4 +144,4 @@
|
|||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -10,6 +10,14 @@
|
|||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
<?php if (!empty($_GET['calendar_error'])) : ?>
|
||||||
|
<div class="container mt-3">
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
Co najmniej jeden bilet jest już niedostępny w wybranym terminie. Zmień datę w koszyku.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<div id="basket_page">
|
<div id="basket_page">
|
||||||
<div class="basket_content">
|
<div class="basket_content">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@@ -202,6 +210,15 @@ $(function() {
|
|||||||
},
|
},
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
response = jQuery.parseJSON(data);
|
response = jQuery.parseJSON(data);
|
||||||
|
if (response.status === 'error') {
|
||||||
|
if ($.alert) {
|
||||||
|
$.alert(response.message);
|
||||||
|
} else {
|
||||||
|
alert(response.message);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$('.box_01').html(response.basket_form);
|
$('.box_01').html(response.basket_form);
|
||||||
$('.box_02 .basket_summary').html(response.basket_summary);
|
$('.box_02 .basket_summary').html(response.basket_summary);
|
||||||
}
|
}
|
||||||
@@ -296,4 +313,4 @@ $(function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,4 +1,13 @@
|
|||||||
<?php
|
<?php
|
||||||
|
$ticketAvailability = $this->ticket_availability ?? [];
|
||||||
|
$isTicketAvailable = static function ($ticketId) use ($ticketAvailability) {
|
||||||
|
if (!array_key_exists($ticketId, $ticketAvailability)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (bool) $ticketAvailability[$ticketId];
|
||||||
|
};
|
||||||
|
|
||||||
if (isset($_POST['selected_date'])) {
|
if (isset($_POST['selected_date'])) {
|
||||||
$selected_date = $_POST['selected_date'];
|
$selected_date = $_POST['selected_date'];
|
||||||
$selected = DateTime::createFromFormat('d-m-Y', $selected_date);
|
$selected = DateTime::createFromFormat('d-m-Y', $selected_date);
|
||||||
@@ -35,6 +44,7 @@ if (isset($_POST['selected_date'])) {
|
|||||||
<script src="https://cdn.jsdelivr.net/npm/flatpickr/dist/l10n/pl.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/flatpickr/dist/l10n/pl.js"></script>
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
|
||||||
|
|
||||||
|
<div id="tickets-main-view">
|
||||||
<div class="tickets_calendar container" >
|
<div class="tickets_calendar container" >
|
||||||
<form id="dateForm" method="POST">
|
<form id="dateForm" method="POST">
|
||||||
<div class="_title">Wybierz datę przyjazdu:</div>
|
<div class="_title">Wybierz datę przyjazdu:</div>
|
||||||
@@ -62,6 +72,7 @@ if (isset($_POST['selected_date'])) {
|
|||||||
</div>
|
</div>
|
||||||
<?php for ($i = 0; $i < $count; $i++) : ?>
|
<?php for ($i = 0; $i < $count; $i++) : ?>
|
||||||
<?php if (isset($ulgowe[$i])) : $item = $ulgowe[$i]; ?>
|
<?php if (isset($ulgowe[$i])) : $item = $ulgowe[$i]; ?>
|
||||||
|
<?php $canBuyTicket = $isTicketAvailable($item); ?>
|
||||||
<div class="ticket">
|
<div class="ticket">
|
||||||
<div class="ticket-description ticket-description--<?= $this->settings['tickets'][$item]['color']; ?>">
|
<div class="ticket-description ticket-description--<?= $this->settings['tickets'][$item]['color']; ?>">
|
||||||
<h3 class="ticket__name"><?= $this->settings['tickets'][$item]['name']; ?></h3>
|
<h3 class="ticket__name"><?= $this->settings['tickets'][$item]['name']; ?></h3>
|
||||||
@@ -74,11 +85,14 @@ if (isset($_POST['selected_date'])) {
|
|||||||
<?php echo date_price($this->settings['tickets'][$item], $days_diff, $is_weekend); ?>
|
<?php echo date_price($this->settings['tickets'][$item], $days_diff, $is_weekend); ?>
|
||||||
</h3>
|
</h3>
|
||||||
<div class="ticket-quantity">
|
<div class="ticket-quantity">
|
||||||
<button class="add button" ticket_id="<?= $item; ?>">Dodaj do koszyka</button>
|
<button class="add button" ticket_id="<?= $item; ?>" <?= $canBuyTicket ? '' : 'disabled'; ?>>
|
||||||
|
<?= $canBuyTicket ? 'Dodaj do koszyka' : 'Niedostępny'; ?>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if (isset($normalne[$i])) : $item = $normalne[$i]; ?>
|
<?php if (isset($normalne[$i])) : $item = $normalne[$i]; ?>
|
||||||
|
<?php $canBuyTicket = $isTicketAvailable($item); ?>
|
||||||
<div class="ticket">
|
<div class="ticket">
|
||||||
<div class="ticket-description ticket-description--<?= $this->settings['tickets'][$item]['color']; ?>">
|
<div class="ticket-description ticket-description--<?= $this->settings['tickets'][$item]['color']; ?>">
|
||||||
<h3 class="ticket__name"><?= $this->settings['tickets'][$item]['name']; ?></h3>
|
<h3 class="ticket__name"><?= $this->settings['tickets'][$item]['name']; ?></h3>
|
||||||
@@ -91,7 +105,9 @@ if (isset($_POST['selected_date'])) {
|
|||||||
<?php echo date_price($this->settings['tickets'][$item], $days_diff, $is_weekend); ?>
|
<?php echo date_price($this->settings['tickets'][$item], $days_diff, $is_weekend); ?>
|
||||||
</h3>
|
</h3>
|
||||||
<div class="ticket-quantity">
|
<div class="ticket-quantity">
|
||||||
<button class="add button" ticket_id="<?= $item; ?>">Dodaj do koszyka</button>
|
<button class="add button" ticket_id="<?= $item; ?>" <?= $canBuyTicket ? '' : 'disabled'; ?>>
|
||||||
|
<?= $canBuyTicket ? 'Dodaj do koszyka' : 'Niedostępny'; ?>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@@ -107,6 +123,7 @@ if (isset($_POST['selected_date'])) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<? foreach($this -> settings['bilety-all-open'] as $key => $item) : ?>
|
<? foreach($this -> settings['bilety-all-open'] as $key => $item) : ?>
|
||||||
|
<?php $canBuyTicket = $isTicketAvailable($item); ?>
|
||||||
<? $pattern = "/All Open -/"; ?>
|
<? $pattern = "/All Open -/"; ?>
|
||||||
<div class="ticket">
|
<div class="ticket">
|
||||||
<div class="ticket-description ticket-description--<?= $this -> settings['tickets'][$item]['color']; ?>">
|
<div class="ticket-description ticket-description--<?= $this -> settings['tickets'][$item]['color']; ?>">
|
||||||
@@ -123,7 +140,9 @@ if (isset($_POST['selected_date'])) {
|
|||||||
?>
|
?>
|
||||||
</h3>
|
</h3>
|
||||||
<div class="ticket-quantity">
|
<div class="ticket-quantity">
|
||||||
<button class="add button" ticket_id="<?= $item; ?>">Dodaj do koszyka</button>
|
<button class="add button" ticket_id="<?= $item; ?>" <?= $canBuyTicket ? '' : 'disabled'; ?>>
|
||||||
|
<?= $canBuyTicket ? 'Dodaj do koszyka' : 'Niedostępny'; ?>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<? endforeach; ?>
|
<? endforeach; ?>
|
||||||
@@ -137,6 +156,7 @@ if (isset($_POST['selected_date'])) {
|
|||||||
<p class="description">bilety dla rodzin</p>
|
<p class="description">bilety dla rodzin</p>
|
||||||
</div>
|
</div>
|
||||||
<? foreach($this -> settings['bilety-rodzinne'] as $key => $item) : ?>
|
<? foreach($this -> settings['bilety-rodzinne'] as $key => $item) : ?>
|
||||||
|
<?php $canBuyTicket = $isTicketAvailable($item); ?>
|
||||||
<div class="ticket">
|
<div class="ticket">
|
||||||
<div class="ticket-description ticket-description--<?= $this -> settings['tickets'][$item]['color']; ?>">
|
<div class="ticket-description ticket-description--<?= $this -> settings['tickets'][$item]['color']; ?>">
|
||||||
<h3 class="ticket__name"><?= $this -> settings['tickets'][$item]['name']; ?></h3>
|
<h3 class="ticket__name"><?= $this -> settings['tickets'][$item]['name']; ?></h3>
|
||||||
@@ -151,7 +171,9 @@ if (isset($_POST['selected_date'])) {
|
|||||||
?>
|
?>
|
||||||
</h3>
|
</h3>
|
||||||
<div class="ticket-quantity">
|
<div class="ticket-quantity">
|
||||||
<button class="add button" ticket_id="<?= $item; ?>">Dodaj do koszyka</button>
|
<button class="add button" ticket_id="<?= $item; ?>" <?= $canBuyTicket ? '' : 'disabled'; ?>>
|
||||||
|
<?= $canBuyTicket ? 'Dodaj do koszyka' : 'Niedostępny'; ?>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<? endforeach; ?>
|
<? endforeach; ?>
|
||||||
@@ -164,6 +186,7 @@ if (isset($_POST['selected_date'])) {
|
|||||||
<p class="description">Na cały sezon</p>
|
<p class="description">Na cały sezon</p>
|
||||||
</div>
|
</div>
|
||||||
<? foreach($this -> settings['karnety'] as $key => $item) : ?>
|
<? foreach($this -> settings['karnety'] as $key => $item) : ?>
|
||||||
|
<?php $canBuyTicket = $isTicketAvailable($item); ?>
|
||||||
<div class="ticket">
|
<div class="ticket">
|
||||||
<div class="ticket-description ticket-description--<?= $this -> settings['tickets'][$item]['color']; ?>">
|
<div class="ticket-description ticket-description--<?= $this -> settings['tickets'][$item]['color']; ?>">
|
||||||
<h3 class="ticket__name"><?= $this -> settings['tickets'][$item]['name']; ?></h3>
|
<h3 class="ticket__name"><?= $this -> settings['tickets'][$item]['name']; ?></h3>
|
||||||
@@ -179,7 +202,9 @@ if (isset($_POST['selected_date'])) {
|
|||||||
?>
|
?>
|
||||||
</h3>
|
</h3>
|
||||||
<div class="ticket-quantity">
|
<div class="ticket-quantity">
|
||||||
<button class="add button" ticket_id="<?= $item; ?>">Dodaj do koszyka</button>
|
<button class="add button" ticket_id="<?= $item; ?>" <?= $canBuyTicket ? '' : 'disabled'; ?>>
|
||||||
|
<?= $canBuyTicket ? 'Dodaj do koszyka' : 'Niedostępny'; ?>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<? endforeach; ?>
|
<? endforeach; ?>
|
||||||
@@ -242,6 +267,7 @@ if (isset($_POST['selected_date'])) {
|
|||||||
<img src="/layout/images/shopping-basket.svg" alt="">
|
<img src="/layout/images/shopping-basket.svg" alt="">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
@@ -297,6 +323,15 @@ $(function() {
|
|||||||
beforeSend: function() {},
|
beforeSend: function() {},
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
response = jQuery.parseJSON(data);
|
response = jQuery.parseJSON(data);
|
||||||
|
if (response.status === 'error') {
|
||||||
|
if ($.alert) {
|
||||||
|
$.alert(response.message);
|
||||||
|
} else {
|
||||||
|
alert(response.message);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$('.shopping-cart-container').html(response.shopping_cart);
|
$('.shopping-cart-container').html(response.shopping_cart);
|
||||||
|
|
||||||
// animacja przycisku
|
// animacja przycisku
|
||||||
@@ -350,7 +385,6 @@ document.addEventListener('onChange', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
var dates = [ "19-05-2025", "20-05-2025", "21-05-2025", "22-05-2025", "23-05-2025", "26-05-2025", "27-05-2025", "28-05-2025", "29-05-2025", "30-05-2025", "02-06-2025", "03-06-2025", "04-06-2025", "05-06-2025", "06-06-2025", "09-06-2025", "10-06-2025", "11-06-2025", "12-06-2025", "13-06-2025", "16-06-2025", "17-06-2025", "18-06-2025", "20-06-2025", "23-06-2025", "24-06-2025", "25-06-2025", "26-06-2025", "27-06-2025" ];
|
|
||||||
flatpickr("#flatpickr", {
|
flatpickr("#flatpickr", {
|
||||||
inline: true,
|
inline: true,
|
||||||
dateFormat: "d-m-Y",
|
dateFormat: "d-m-Y",
|
||||||
@@ -358,11 +392,10 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
minDate: "today",
|
minDate: "today",
|
||||||
locale: "pl",
|
locale: "pl",
|
||||||
theme: "material_blue",
|
theme: "material_blue",
|
||||||
disable: dates,
|
|
||||||
onChange: function(selectedDates, dateStr, instance) {
|
onChange: function(selectedDates, dateStr, instance) {
|
||||||
document.getElementById('dateForm').submit();
|
document.getElementById('dateForm').submit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -29,6 +29,13 @@ $migrations = [
|
|||||||
|
|
||||||
'ticket_prices_add_price_weekend' => "ALTER TABLE ticket_prices ADD COLUMN IF NOT EXISTS price_weekend DECIMAL(10,2) DEFAULT NULL AFTER price",
|
'ticket_prices_add_price_weekend' => "ALTER TABLE ticket_prices ADD COLUMN IF NOT EXISTS price_weekend DECIMAL(10,2) DEFAULT NULL AFTER price",
|
||||||
|
|
||||||
|
'ticket_calendar_availability' => "CREATE TABLE IF NOT EXISTS ticket_calendar_availability (
|
||||||
|
ticket_group VARCHAR(64) NOT NULL,
|
||||||
|
available_date DATE NOT NULL,
|
||||||
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (ticket_group, available_date)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8",
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
$ok = 0;
|
$ok = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user