diff --git a/juconnect-capacity-status-plugin/juconnect-capacity-status.zip b/juconnect-capacity-status-plugin/juconnect-capacity-status.zip new file mode 100644 index 0000000..064147f Binary files /dev/null and b/juconnect-capacity-status-plugin/juconnect-capacity-status.zip differ diff --git a/juconnect-capacity-status-plugin/juconnect-capacity-status/assets/css/juconnect-capacity-status.css b/juconnect-capacity-status-plugin/juconnect-capacity-status/assets/css/juconnect-capacity-status.css new file mode 100644 index 0000000..2838e58 --- /dev/null +++ b/juconnect-capacity-status-plugin/juconnect-capacity-status/assets/css/juconnect-capacity-status.css @@ -0,0 +1,38 @@ +.juconnect-capacity-indicator { + display: inline-flex; + align-items: center; + gap: 10px; + margin: 0 0 var(--s3, 14px) 0; + max-width: 100%; + border-radius: 999px; + border: 1px solid var(--line, #d7dee5); + background: var(--surface, #ffffff); + color: var(--text2, #3c4a58); + padding: 8px 12px; + font-size: var(--fs-s, 0.92rem); + line-height: 1.35; +} + +.juconnect-capacity-indicator .pill__dot { + width: 10px; + height: 10px; + flex: 0 0 auto; + border-radius: 999px; + background: var(--juconnect-capacity-dot, #2f855a); +} + +.hero__inner > .juconnect-capacity-indicator { + margin-top: 0; +} + +.juconnect-capacity-indicator--limited { + --juconnect-capacity-dot: #b7791f; +} + +.juconnect-capacity-indicator--full { + --juconnect-capacity-dot: #c53030; +} + +.juconnect-capacity-indicator--paused { + --juconnect-capacity-dot: #2b6cb0; +} diff --git a/juconnect-capacity-status-plugin/juconnect-capacity-status/juconnect-capacity-status.php b/juconnect-capacity-status-plugin/juconnect-capacity-status/juconnect-capacity-status.php new file mode 100644 index 0000000..4f10eb0 --- /dev/null +++ b/juconnect-capacity-status-plugin/juconnect-capacity-status/juconnect-capacity-status.php @@ -0,0 +1,385 @@ + 1, + 'placement' => 'front_page', + 'status' => 'available', + 'text' => 'Kapazitaeten frei', + 'dot_color' => '#2f855a', + ]; +} + +function juconnect_capacity_status_options() { + return [ + 'available' => __('Kapazitaeten frei', 'juconnect'), + 'limited' => __('Wenige Kapazitaeten frei', 'juconnect'), + 'full' => __('Aktuell keine Kapazitaeten frei', 'juconnect'), + 'paused' => __('Aufnahme pausiert', 'juconnect'), + ]; +} + +function juconnect_capacity_placement_options() { + return [ + 'front_page' => __('Nur auf der Startseite', 'juconnect'), + 'all_hero' => __('Auf allen Seiten mit Hero', 'juconnect'), + ]; +} + +function juconnect_capacity_get_settings() { + $settings = get_option(JUCONNECT_CAPACITY_OPTION_KEY, []); + if (!is_array($settings)) { + $settings = []; + } + + return wp_parse_args($settings, juconnect_capacity_default_settings()); +} + +function juconnect_capacity_default_color_for_status($status) { + $status_colors = [ + 'available' => '#2f855a', + 'limited' => '#b7791f', + 'full' => '#c53030', + 'paused' => '#2b6cb0', + ]; + + return $status_colors[$status] ?? '#2f855a'; +} + +register_activation_hook(__FILE__, function () { + if (false === get_option(JUCONNECT_CAPACITY_OPTION_KEY, false)) { + add_option(JUCONNECT_CAPACITY_OPTION_KEY, juconnect_capacity_default_settings()); + } +}); + +function juconnect_capacity_sanitize_settings($input) { + if (!is_array($input)) { + $input = []; + } + + $defaults = juconnect_capacity_default_settings(); + $statuses = juconnect_capacity_status_options(); + $placements = juconnect_capacity_placement_options(); + + $sanitized = []; + $sanitized['enabled'] = empty($input['enabled']) ? 0 : 1; + + $placement = isset($input['placement']) ? sanitize_key($input['placement']) : $defaults['placement']; + $sanitized['placement'] = array_key_exists($placement, $placements) ? $placement : $defaults['placement']; + + $status = isset($input['status']) ? sanitize_key($input['status']) : $defaults['status']; + $sanitized['status'] = array_key_exists($status, $statuses) ? $status : $defaults['status']; + + $text = isset($input['text']) ? sanitize_text_field($input['text']) : ''; + $sanitized['text'] = '' === $text ? $statuses[$sanitized['status']] : $text; + + $dot_color = isset($input['dot_color']) ? sanitize_hex_color($input['dot_color']) : ''; + if (!$dot_color) { + $dot_color = juconnect_capacity_default_color_for_status($sanitized['status']); + } + $sanitized['dot_color'] = $dot_color; + + return $sanitized; +} + +add_action('admin_init', function () { + register_setting('juconnect_capacity_settings_group', JUCONNECT_CAPACITY_OPTION_KEY, [ + 'type' => 'array', + 'sanitize_callback' => 'juconnect_capacity_sanitize_settings', + 'default' => juconnect_capacity_default_settings(), + ]); + + add_settings_section( + 'juconnect_capacity_main_section', + __('Kapazitaetsanzeige', 'juconnect'), + function () { + echo '
' . esc_html__('Steuert die Kapazitaetsanzeige im oberen Bereich des Hero-Blocks.', 'juconnect') . '
'; + }, + 'juconnect-capacity-settings' + ); + + add_settings_field( + 'juconnect_capacity_enabled', + __('Anzeige aktiv', 'juconnect'), + 'juconnect_capacity_render_enabled_field', + 'juconnect-capacity-settings', + 'juconnect_capacity_main_section' + ); + + add_settings_field( + 'juconnect_capacity_placement', + __('Platzierung', 'juconnect'), + 'juconnect_capacity_render_placement_field', + 'juconnect-capacity-settings', + 'juconnect_capacity_main_section' + ); + + add_settings_field( + 'juconnect_capacity_status', + __('Status', 'juconnect'), + 'juconnect_capacity_render_status_field', + 'juconnect-capacity-settings', + 'juconnect_capacity_main_section' + ); + + add_settings_field( + 'juconnect_capacity_text', + __('Textinhalt', 'juconnect'), + 'juconnect_capacity_render_text_field', + 'juconnect-capacity-settings', + 'juconnect_capacity_main_section' + ); + + add_settings_field( + 'juconnect_capacity_dot_color', + __('Punktfarbe', 'juconnect'), + 'juconnect_capacity_render_dot_color_field', + 'juconnect-capacity-settings', + 'juconnect_capacity_main_section' + ); +}); + +add_action('admin_menu', function () { + add_options_page( + __('JuConnect Kapazitaetsanzeige', 'juconnect'), + __('Kapazitaetsanzeige', 'juconnect'), + 'manage_options', + 'juconnect-capacity-settings', + 'juconnect_capacity_render_settings_page' + ); +}); + +function juconnect_capacity_render_settings_page() { + if (!current_user_can('manage_options')) { + return; + } + ?> ++ +
+ + + ' + . '' + . '' . esc_html($text) . '' + . ''; +} + +add_shortcode('juconnect_capacity_status', function () { + return juconnect_capacity_render_indicator_markup(); +}); + +add_filter('render_block', function ($block_content, $block) { + static $inserted = false; + + if ($inserted || !juconnect_capacity_should_inject()) { + return $block_content; + } + + if (!is_array($block) || empty($block['blockName']) || 'core/group' !== $block['blockName']) { + return $block_content; + } + + $class_name = $block['attrs']['className'] ?? ''; + if (!is_string($class_name) || '' === trim($class_name)) { + return $block_content; + } + + $target_classes = ['hero__inner', 'pagehead__left', 'pagehead']; + $matched_target_class = ''; + foreach ($target_classes as $target_class) { + if (false !== strpos(' ' . $class_name . ' ', ' ' . $target_class . ' ')) { + $matched_target_class = $target_class; + break; + } + } + + if ('' === $matched_target_class) { + return $block_content; + } + + $indicator = juconnect_capacity_render_indicator_markup(); + if ('' === $indicator) { + return $block_content; + } + + $inserted = true; + + $target_pattern = preg_quote($matched_target_class, '/'); + $injected = preg_replace( + '/(