start_controls_section( 'section_faces', array( 'label' => __( 'Faces', 'a1-tools' ) ) ); $this->add_control( 'prompt_title', array( 'label' => __( 'Title', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( 'How was your experience?', 'a1-tools' ), 'label_block' => true, ) ); $this->add_control( 'prompt_subtitle', array( 'label' => __( 'Subtitle', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( 'Tap a face to let us know.', 'a1-tools' ), 'label_block' => true, ) ); $this->add_control( 'face_style', array( 'label' => __( 'Face Style', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SELECT, 'default' => 'classic', 'options' => array( 'classic' => __( 'Classic (outlined smileys)', 'a1-tools' ), 'emoji' => __( 'Emoji', 'a1-tools' ), ), ) ); $this->add_control( 'happy_first', array( 'label' => __( 'Happy Face on the Left', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'return_value' => 'yes', 'default' => '', 'description' => __( 'Off: sad face on the left, happy face on the right.', 'a1-tools' ), ) ); $this->add_control( 'happy_face', array( 'label' => __( 'Happy Face', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => '😊', 'description' => __( 'Any emoji or character.', 'a1-tools' ), 'condition' => array( 'face_style' => 'emoji' ), ) ); $this->add_control( 'sad_face', array( 'label' => __( 'Sad Face', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => '☹️', 'condition' => array( 'face_style' => 'emoji' ), ) ); $this->add_control( 'show_face_labels', array( 'label' => __( 'Show Labels Under Faces', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'return_value' => 'yes', 'default' => 'yes', ) ); $this->add_control( 'happy_label', array( 'label' => __( 'Happy Label', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( 'Great!', 'a1-tools' ), 'condition' => array( 'show_face_labels' => 'yes' ), ) ); $this->add_control( 'sad_label', array( 'label' => __( 'Sad Label', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( 'Not so great', 'a1-tools' ), 'condition' => array( 'show_face_labels' => 'yes' ), ) ); $this->add_control( 'review_url_override', array( 'label' => __( 'Review Link (override)', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::URL, 'options' => false, 'description' => __( 'Leave empty to use the site Review Link variable (falls back to the Google Business URL) — same resolution as the A1 Review Funnel.', 'a1-tools' ), ) ); $this->add_control( 'open_new_tab', array( 'label' => __( 'Open Review Link in New Tab', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'return_value' => 'yes', 'default' => 'yes', ) ); $this->end_controls_section(); // ── Content : Happy Panel (happy face) ────────────────────── $this->start_controls_section( 'section_positive', array( 'label' => __( 'Happy Panel (happy face)', 'a1-tools' ) ) ); $this->add_control( 'positive_title', array( 'label' => __( 'Header', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( 'So glad we hit the mark! 🎉', 'a1-tools' ), 'label_block' => true, ) ); $this->add_control( 'positive_message', array( 'label' => __( 'Message (optional)', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXTAREA, 'default' => '', 'rows' => 2, ) ); $this->add_control( 'positive_button_label', array( 'label' => __( 'Review Button Label', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( 'Leave a Review on Google', 'a1-tools' ), 'label_block' => true, ) ); $this->add_control( 'happy_thanks_message', array( 'label' => __( 'Thank-You (no link configured)', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( 'Thank you! 🎉', 'a1-tools' ), 'label_block' => true, 'description' => __( 'Shown in place of the review button only when no review link is configured.', 'a1-tools' ), ) ); $this->end_controls_section(); // ── Content : Feedback Form (sad path) ────────────────────── $this->start_controls_section( 'section_negative', array( 'label' => __( 'Feedback Form (sad face)', 'a1-tools' ) ) ); $this->add_control( 'negative_title', array( 'label' => __( 'Title', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( "We're sorry we missed the mark", 'a1-tools' ), 'label_block' => true, ) ); $this->add_control( 'negative_message', array( 'label' => __( 'Message', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXTAREA, 'default' => __( 'Tell us what went wrong and how we can make it right.', 'a1-tools' ), ) ); $this->add_control( 'name_label', array( 'label' => __( 'Name Label', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( 'Your name', 'a1-tools' ), ) ); $this->add_control( 'phone_label', array( 'label' => __( 'Phone Label', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( 'Phone', 'a1-tools' ), ) ); $this->add_control( 'email_label', array( 'label' => __( 'Email Label', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( 'Email', 'a1-tools' ), ) ); $this->add_control( 'feedback_label', array( 'label' => __( 'Feedback Label', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( 'What happened?', 'a1-tools' ), ) ); $this->add_control( 'negative_submit_label', array( 'label' => __( 'Submit Button Label', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( 'Send feedback', 'a1-tools' ), ) ); $this->add_control( 'success_message', array( 'label' => __( 'Success Message', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( "Thank you — we've received your feedback and will be in touch shortly.", 'a1-tools' ), 'label_block' => true, ) ); $this->add_control( 'error_message', array( 'label' => __( 'Error Message', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( 'Sorry, something went wrong. Please try again or call us.', 'a1-tools' ), 'label_block' => true, ) ); $this->add_control( 'negative_google_prompt', array( 'label' => __( 'Public-Review Prompt (after feedback)', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXTAREA, 'default' => __( "If you'd like, you can also share your experience publicly on Google. It only takes a moment.", 'a1-tools' ), 'description' => __( 'Shown with the public review link after private feedback is sent. Hiding the public option from unhappy customers ("review gating") violates Google policy and the FTC rule, so it is always offered.', 'a1-tools' ), ) ); $this->end_controls_section(); // ── Style : Faces ─────────────────────────────────────────── $this->start_controls_section( 'style_faces', array( 'label' => __( 'Faces', 'a1-tools' ), 'tab' => \Elementor\Controls_Manager::TAB_STYLE ) ); $this->add_responsive_control( 'face_size', array( 'label' => __( 'Face Size', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SLIDER, 'size_units' => array( 'px' ), 'range' => array( 'px' => array( 'min' => 24, 'max' => 160 ) ), 'default' => array( 'size' => 56, 'unit' => 'px' ), 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__emoji' => 'font-size: {{SIZE}}{{UNIT}};', '{{WRAPPER}} .a1tools-smiley__svg' => 'width: {{SIZE}}{{UNIT}}; height: {{SIZE}}{{UNIT}};', ), ) ); $this->add_responsive_control( 'faces_gap', array( 'label' => __( 'Gap Between Faces', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SLIDER, 'size_units' => array( 'px' ), 'range' => array( 'px' => array( 'min' => 0, 'max' => 120 ) ), 'default' => array( 'size' => 32, 'unit' => 'px' ), 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__faces' => 'gap: {{SIZE}}{{UNIT}};' ), ) ); $this->add_responsive_control( 'face_padding', array( 'label' => __( 'Button Padding', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SLIDER, 'size_units' => array( 'px' ), 'range' => array( 'px' => array( 'min' => 0, 'max' => 60 ) ), 'default' => array( 'size' => 18, 'unit' => 'px' ), 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__disc' => 'padding: {{SIZE}}{{UNIT}};' ), ) ); $this->add_control( 'face_radius', array( 'label' => __( 'Border Radius', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SLIDER, 'size_units' => array( 'px', '%' ), 'range' => array( 'px' => array( 'min' => 0, 'max' => 100 ), '%' => array( 'min' => 0, 'max' => 50 ), ), 'default' => array( 'size' => 50, 'unit' => '%' ), 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__disc' => 'border-radius: {{SIZE}}{{UNIT}};' ), ) ); $this->add_group_control( \Elementor\Group_Control_Border::get_type(), array( 'name' => 'face_border', 'selector' => '{{WRAPPER}} .a1tools-smiley__disc' ) ); $this->add_control( 'face_fill', array( 'label' => __( 'Face Fill', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'description' => __( 'Inside of the smiley. Defaults to translucent white — use the alpha slider for anything from clear to solid.', 'a1-tools' ), 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__svg circle' => 'fill: {{VALUE}};' ), 'condition' => array( 'face_style' => 'classic' ), ) ); $this->start_controls_tabs( 'faces_tabs' ); $this->start_controls_tab( 'faces_tab_happy', array( 'label' => __( 'Happy', 'a1-tools' ) ) ); $this->add_control( 'happy_face_color', array( 'label' => __( 'Face Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'default' => '#22B24C', 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__face--happy .a1tools-smiley__svg' => 'color: {{VALUE}};' ), 'condition' => array( 'face_style' => 'classic' ), ) ); $this->add_control( 'happy_face_color_hover', array( 'label' => __( 'Face Color (Hover)', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__face--happy:hover .a1tools-smiley__svg' => 'color: {{VALUE}};' ), 'condition' => array( 'face_style' => 'classic' ), ) ); $this->add_control( 'happy_bg', array( 'label' => __( 'Background', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__face--happy .a1tools-smiley__disc' => 'background-color: {{VALUE}};' ), ) ); $this->add_control( 'happy_bg_hover', array( 'label' => __( 'Background (Hover)', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__face--happy:hover .a1tools-smiley__disc' => 'background-color: {{VALUE}};' ), ) ); $this->end_controls_tab(); $this->start_controls_tab( 'faces_tab_sad', array( 'label' => __( 'Sad', 'a1-tools' ) ) ); $this->add_control( 'sad_face_color', array( 'label' => __( 'Face Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'default' => '#E23D4B', 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__face--sad .a1tools-smiley__svg' => 'color: {{VALUE}};' ), 'condition' => array( 'face_style' => 'classic' ), ) ); $this->add_control( 'sad_face_color_hover', array( 'label' => __( 'Face Color (Hover)', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__face--sad:hover .a1tools-smiley__svg' => 'color: {{VALUE}};' ), 'condition' => array( 'face_style' => 'classic' ), ) ); $this->add_control( 'sad_bg', array( 'label' => __( 'Background', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__face--sad .a1tools-smiley__disc' => 'background-color: {{VALUE}};' ), ) ); $this->add_control( 'sad_bg_hover', array( 'label' => __( 'Background (Hover)', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__face--sad:hover .a1tools-smiley__disc' => 'background-color: {{VALUE}};' ), ) ); $this->end_controls_tab(); $this->end_controls_tabs(); $this->add_control( 'face_labels_heading', array( 'label' => __( 'Face Labels', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::HEADING, 'separator' => 'before', 'condition' => array( 'show_face_labels' => 'yes' ), ) ); $this->add_control( 'face_label_color', array( 'label' => __( 'Label Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'condition' => array( 'show_face_labels' => 'yes' ), 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__face-label' => 'color: {{VALUE}};' ), ) ); $this->add_group_control( \Elementor\Group_Control_Typography::get_type(), array( 'name' => 'face_label_typography', 'selector' => '{{WRAPPER}} .a1tools-smiley__face-label', 'condition' => array( 'show_face_labels' => 'yes' ), ) ); $this->end_controls_section(); // ── Style : Title & Text ──────────────────────────────────── $this->start_controls_section( 'style_text', array( 'label' => __( 'Title & Text', 'a1-tools' ), 'tab' => \Elementor\Controls_Manager::TAB_STYLE ) ); $this->add_control( 'title_color', array( 'label' => __( 'Title Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__title' => 'color: {{VALUE}};' ), ) ); $this->add_group_control( \Elementor\Group_Control_Typography::get_type(), array( 'name' => 'title_typography', 'selector' => '{{WRAPPER}} .a1tools-smiley__title' ) ); $this->add_control( 'text_color', array( 'label' => __( 'Text Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__text' => 'color: {{VALUE}};' ), ) ); $this->add_group_control( \Elementor\Group_Control_Typography::get_type(), array( 'name' => 'text_typography', 'selector' => '{{WRAPPER}} .a1tools-smiley__text' ) ); $this->add_responsive_control( 'content_align', array( 'label' => __( 'Alignment', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::CHOOSE, 'options' => array( 'left' => array( 'title' => __( 'Left', 'a1-tools' ), 'icon' => 'eicon-text-align-left' ), 'center' => array( 'title' => __( 'Center', 'a1-tools' ), 'icon' => 'eicon-text-align-center' ), 'right' => array( 'title' => __( 'Right', 'a1-tools' ), 'icon' => 'eicon-text-align-right' ), ), 'default' => 'center', 'selectors' => array( '{{WRAPPER}} .a1tools-smiley' => 'text-align: {{VALUE}};', '{{WRAPPER}} .a1tools-smiley__faces' => 'justify-content: {{VALUE}};', ), ) ); $this->end_controls_section(); // ── Style : Form ──────────────────────────────────────────── $this->start_controls_section( 'style_form', array( 'label' => __( 'Feedback Form', 'a1-tools' ), 'tab' => \Elementor\Controls_Manager::TAB_STYLE ) ); $this->add_control( 'form_label_color', array( 'label' => __( 'Field Label Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__label' => 'color: {{VALUE}};' ), ) ); $this->add_control( 'input_text_color', array( 'label' => __( 'Input Text', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__input, {{WRAPPER}} .a1tools-smiley__textarea' => 'color: {{VALUE}};' ), ) ); $this->add_control( 'input_bg_color', array( 'label' => __( 'Input Background', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__input, {{WRAPPER}} .a1tools-smiley__textarea' => 'background-color: {{VALUE}};' ), ) ); $this->add_control( 'input_border_color', array( 'label' => __( 'Input Border', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__input, {{WRAPPER}} .a1tools-smiley__textarea' => 'border-color: {{VALUE}};' ), ) ); $this->add_control( 'buttons_heading', array( 'label' => __( 'Buttons (submit + review link)', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::HEADING, 'separator' => 'before', ) ); $this->start_controls_tabs( 'btn_tabs' ); $this->start_controls_tab( 'btn_tab_normal', array( 'label' => __( 'Normal', 'a1-tools' ) ) ); $this->add_control( 'btn_color', array( 'label' => __( 'Text', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__btn' => 'color: {{VALUE}};' ), ) ); $this->add_control( 'btn_bg', array( 'label' => __( 'Background', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'default' => '#F49321', 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__btn' => 'background-color: {{VALUE}};' ), ) ); $this->end_controls_tab(); $this->start_controls_tab( 'btn_tab_hover', array( 'label' => __( 'Hover', 'a1-tools' ) ) ); $this->add_control( 'btn_color_hover', array( 'label' => __( 'Text', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__btn:hover' => 'color: {{VALUE}};' ), ) ); $this->add_control( 'btn_bg_hover', array( 'label' => __( 'Background', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'default' => '#F67000', 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__btn:hover' => 'background-color: {{VALUE}};' ), ) ); $this->end_controls_tab(); $this->end_controls_tabs(); $this->add_control( 'msg_heading', array( 'label' => __( 'Status Messages', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::HEADING, 'separator' => 'before', ) ); $this->add_control( 'success_color', array( 'label' => __( 'Success Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__feedback--success' => 'color: {{VALUE}};' ), ) ); $this->add_control( 'error_color', array( 'label' => __( 'Error Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-smiley__feedback--error' => 'color: {{VALUE}};' ), ) ); $this->end_controls_section(); } /** * Render widget output on the frontend. */ /** * Markup for one face glyph — either the built-in outlined SVG smiley * (white face, colored outline/eyes/mouth via currentColor, like the * classic green/red survey faces) or a user-chosen emoji. * * @param string $type 'happy' or 'sad'. * @param array $s Widget settings. * @return string Safe HTML. */ private function face_glyph( $type, $s ) { if ( 'emoji' === ( $s['face_style'] ?? 'classic' ) ) { $default = 'happy' === $type ? '😊' : '☹️'; $char = trim( (string) ( $s[ $type . '_face' ] ?? '' ) ); return ''; } $mouth = 'happy' === $type ? '' : ''; return ''; } protected function render() { $s = $this->get_settings_for_display(); // Public review URL — identical resolution to the A1 Review Funnel. $override = isset( $s['review_url_override'] ) ? ( is_array( $s['review_url_override'] ) ? ( $s['review_url_override']['url'] ?? '' ) : $s['review_url_override'] ) : ''; $review_url = function_exists( 'a1tools_resolve_review_url' ) ? a1tools_resolve_review_url( $override ) : trim( (string) $override ); // CRM company — same auto-resolution the funnel uses. $company_id = (int) get_option( 'a1tools_form_crm_company_id', 0 ); if ( 0 === $company_id && function_exists( 'a1tools_resolve_crm_company_id' ) ) { $company_id = (int) a1tools_resolve_crm_company_id(); } $rest_url = esc_url_raw( rest_url( 'a1-tools/v1/submit-review' ) ); $page_url = esc_url( is_singular() ? get_permalink() : home_url( add_query_arg( null, null ) ) ); $show_labels = 'yes' === ( $s['show_face_labels'] ?? 'yes' ); $new_tab = 'yes' === ( $s['open_new_tab'] ?? 'yes' ); $happy_first = 'yes' === ( $s['happy_first'] ?? '' ); // Build both faces up front, then print them in the chosen order — // sad/red on the LEFT by default; "Happy Face on the Left" swaps them. // DOM order matches visual order, so tab order stays sane. // The happy face reveals the positive panel (header + Google review // button) instead of navigating straight to the review link. ob_start(); ?>